J'ai besoin d'une suggestion pour créer un SQL à la place d'une fonction pour ce cas (SQL Server)

C'est pour une database SQL Server 2016.

J'ai deux tables, comme ci-dessous:

Tableau A :

  • GlobalId uniqueidentifier,
  • Date datetime2,
  • La description

Tableau B :

  • GlobalId uniqueidentifier,
  • Rel_GlobalId uniqueidentifier,
  • Nom de file nvarchar (250),
  • Date datetime2

La relation entre la table A et la table B est 1-to-many, ou 'Une ligne du tableau A contient une ou plusieurs lignes de la table B'

B contient toujours une ou plusieurs lignes appartenant à A. Mais je n'ai besoin que de la première et de la dernière ligne (sortingées par date dans le tableau B). Ainsi, même une ligne du tableau A contient 10 lignes du tableau B, premier et les derniers rangs de B. Si A n'a que 1 B, j'ai besoin seulement du premier B.

Je dois returnner la valeur au format suivant:

GlobalId (from A), First_File (GlobalId from B), Last_File (GlobalID from B), First_File_Num*, Last_File_Num* 

Le First_File_Num et Last_File_Num est un nombre séquentiel, commençant de 1 à l'infini, mais il s'agit d'un seul numéro séquentiel. Si A a deux B, first_file_num = 1, et last_file_num = 2. Sur les lignes consécutives, ce nombre séquentiel doit continuer à partir de la dernière ligne, donc, doit être 3 et 4, puis 5 et 6, etc. , l'incrément est seulement 1 pour cette ligne.

Pour rendre les choses plus claires (et parce que l'anglais n'est pas ma langue principale), prenez ceci comme exemple:

Tableau A :

 +----------+------------+----------------+ | GlobalId | Date | Description | +----------+------------+----------------+ | aa | 2016-12-06 | Description 01 | | ab | 2016-12-07 | Description 02 | | ac | 2016-12-07 | Description 03 | +----------+------------+----------------+ 

Tableau B :

 +----------+--------------+------------+---------------------+ | GlobalId | Rel_GlobalId | Filename | Date | +----------+--------------+------------+---------------------+ | ba | aa | file02.jpg | 2016-12-06 05:13:25 | | bb | aa | file01.jpg | 2016-12-06 03:45:12 | | bc | ab | file03.jpg | 2016-12-07 08:54:31 | | bd | ac | file05.jpg | 2016-12-07 11:39:19 | | be | ac | file04.jpg | 2016-12-07 10:48:13 | | bf | ac | file06.jpg | 2016-12-07 15:08:17 | +----------+--------------+------------+---------------------+ 

La relation entre le tableau A et la table B est A.GlobalId = B.Rel_GlobalId

Donc, maintenant, je dois returnner une table avec datatables suivantes:

 +----------+------------+-----------+----------------+---------------+ | GlobalId | First_File | Last_File | First_File_Num | Last_File_Num | +----------+------------+-----------+----------------+---------------+ | aa | bb | ba | 01 | 02 | | ab | bc | NULL | 03 | NULL | | ac | be | bf | 04 | 05 | +----------+------------+-----------+----------------+---------------+ 

Pour résoudre ce problème, j'ai créé une fonction (fonction de valeur de table), mais j'aime savoir si cela est possible seulement avec des vues (même si je dois créer plus d'une vue) – juste pour la curiosité: D

/ * J'ai besoin d'une suggestion pour créer un SQL à la place d'une fonction pour ce cas (SQL Server) * / J'ai besoin d'une suggestion pour créer un SQL à la place d'une fonction pour ce cas (SQL Server)

Vous pouvez le faire en utilisant un cte et en utilisant plusieurs row_number() s (comme dit HoneyBadger dans son commentaire).

rextester: http://rextester.com/FHQIL42952

 create table a ( globalid varchar(36) not null primary key , date datetime2(2) not null , description varchar(128) not null ); create table b ( rel_globalid varchar(36) not null , globalid varchar(36) not null , filename varchar(128) not null , date datetime2(2) not null ); insert into a (globalid, date, description) values ('aa','2016-12-06','Description 01') , ('ab','2016-12-07','Description 02') , ('ac','2016-12-07','Description 03'); insert into b (globalid, rel_globalid, filename, date) values ('ba','aa','file02.jpg','2016-12-06T05:13:25') ,('bb','aa','file01.jpg','2016-12-06T03:45:12') ,('bc','ab','file03.jpg','2016-12-07T08:54:31') ,('bd','ac','file05.jpg','2016-12-07T11:39:19') ,('be','ac','file04.jpg','2016-12-07T10:48:13') ,('bf','ac','file06.jpg','2016-12-07T15:08:17'); with cte as ( select globalid , rel_globalid , filename , date , rn_a = row_number() over (partition by rel_globalid order by date asc) , rn_d = row_number() over (partition by rel_globalid order by date desc) from b ) , x as ( select globalid , rel_globalid , filename , date , rn_a , rn_d , seq = row_number() over (order by globalid, date asc) from cte where rn_a = 1 or rn_d = 1 ) select a.globalid , first_file = ba.globalid , last_file = bd.globalid , first_file_num = ba.seq , last_file_num = bd.seq from a left join x as ba on a.globalid = ba.rel_globalid and ba.rn_a = 1 left join x as bd on a.globalid = bd.rel_globalid and bd.rn_d = 1 and bd.rn_a !=1 order by a.globalid; 

Résulte en:

 globalid first_file last_file first_file_num last_file_num aa bb ba 1 2 ab bc NULL 3 NULL ac be bf 4 5 

Je préférerais créer une fonction qui returnne la dernière ligne d'un logging puis créer une procédure stockée qui renvoie la première ligne et appliquer une croix à la fonction, l'opérateur apply est très utile et parce que ça ne fonctionne pas comme interne rejoint l'impact dans la requête de sélection est très faible