2009-10-15 4 views
1

J'ai le script suivant:Serait-ce une situation appropriée pour un curseur?

SELECT left(SHI.FSOKEY, 6) AS [SoNo] 
,  substring(SHI.FSOKEY, 7, 3) AS [So Item] 
,  right(SHI.FSOKEY, 3) AS [So Rels] 
,  QAL.FCLOT AS [LotSerial] 

FROM shmast SHM 
    INNER JOIN shitem SHI 
    ON SHM.FSHIPNO = SHI.FSHIPNO 
    INNER JOIN qalotc QAL 
    ON SHM.FSHIPNO = Left(QAL.FCUSEINDOC, 6) 
     AND substring(QAL.FCUSEINDOC, 7, 6) = SHI.FITEMNO 

Ce produit sortie qui ressemble à ceci:

SoNo  So Item SoRels LotSerial 
123456  1  001  ABCD 
123456  1  001  AMOH 
123456  1  001  POWK 
123456  1  001  IUIL 
123456  1  002  ABCE 

Je veux groupe par SONO, Soitem, et Sorels obtenir une liste des LotSerials pour chacun. Donc, ma sortie ressemblerait à ceci:

SoNo  So Item SoRels LotSerial 
123456  1  001  ABCD, AMOH, POWK, IUIL 
123456  1  002  ABCE 

que je dois faire pour que je puisse tirer cette information dans une requête principale sur la base des SoNo, Soitem, Sorels.

Toute aide serait grandement appréciée.

Répondre

2

@cmsjr beat me to it with his answer qui est juste combat même. Je construis la chaîne différemment, et j'ai un exemple de travail complet.

essayez ceci:

CREATE TABLE YourTable (SoNo int, SoItem int, SoRels char(3), LotSerial char(4)) 
go 
INSERT INTO YourTable VALUES (123456,1,'001','ABCD') 
INSERT INTO YourTable VALUES (123456,1,'001','AMOH') 
INSERT INTO YourTable VALUES (123456,1,'001','POWK') 
INSERT INTO YourTable VALUES (123456,1,'001','IUIL') 
INSERT INTO YourTable VALUES (123456,1,'002','ABCE') 
go 
CREATE FUNCTION LotSerial_to_CVS(@SoNo int, @SoItem int, @SoRels char(3)) 
RETURNS varchar(2000) AS 
BEGIN 
    DECLARE @cvs varchar(2000) 
    SELECT @cvs=ISNULL(@cvs+', ','')+LotSerial 
     FROM YourTable 
     WHERE [email protected] AND [email protected] AND [email protected] 
    RETURN @cvs 
END 
go 

SELECT 
    SoNo, SoItem, SoRels, dbo.LotSerial_to_CVS(SoNo, SoItem, SoRels) 
    FROM YourTable 
     GROUP BY SoNo, SoItem, SoRels 

SORTIE:

SoNo  SoItem  SoRels 
----------- ----------- ------ ----------------------- 
123456  1   001 ABCD, AMOH, POWK, IUIL 
123456  1   002 ABCE 

(2 row(s) affected) 
5

Comme toujours, évitez autant que possible les curseurs. Votre scénario conviendrait parfaitement à une fonction définie par l'utilisateur. J'ai un peu simplifié votre schéma pour cet exemple. Essentiellement, nous concaténons les séries qui correspondent avec des virgules à une variable dans une fonction définie par l'utilisateur, puis nous réaccordons le résultat. Si les valeurs nulles sont possibles, vous voudrez peut-être ajouter l'utilisation de Coalesce

create table SO (SONO int) 
insert into SO values (1) 
insert into SO values (2) 
insert into SO values (3) 


create table SOCHILD 
(SONO int, SerialNo varchar(10)) 
insert into SOCHILD values (1, 'ABCD') 
insert into SOCHILD values (1, 'EFGH') 
insert into SOCHILD values (1, 'IJKL') 
GO 
create function fx_GetSerials(@SONO int) 
returns varchar(1000) as 
Begin 
    Declare @ret varchar(1000) 
    set @ret = '' 
    Select @ret = @ret + SerialNo + ',' 
    from SOCHILD where SONO = @SONO 
    if (len(@ret) > 0) 
     set @Ret = left(@ret, len(@ret) -1) 
    return @ret 
End 
GO 
select dbo.Fx_GetSerials(1) 
drop function fx_GetSerials 
Drop table SO 
Drop table SOCHILD 

Résultats ABCD, EFGH, IJKL

+0

+1 Exactement ma pensée. Mais vous devriez faire attention, car lorsque le SELECT ne retournera rien, la fonction LEFT retournera l'erreur !! –

+0

Grand point, vérification de longueur ajoutée. – cmsjr

+0

puisque cette fonction sera exécutée pour chaque ligne retournée, vous devez la faire tourner aussi vite que possible. ma version fonctionnera beaucoup plus vite, elle n'a pas le code dont cette version a besoin pour couper la virgule. L'astuce consiste à gérer les NULL. dans mon code: _ @ cvs = ISNULL (@ cvs + ',', '') + LotSerial_ quand @cvs est nul, la virgule initiale est perdue lors de la concaténation de null + ','. cependant le ISNULL() autour de ce qui l'oblige à être une chaîne vide et à concaténer avec la première chaîne correctement. Sur toutes les concaténations suivantes, @ cvs + ',' donne une chaîne valide, ce qui vous donne des virgules si nécessaire. –

1

Il n'y a pas besoin d'un curseur dans presque tous les cas plus.

Vous pouvez faire la même chose en utilisant XML PATH. Voici un exemple de travail:

SET NOCOUNT ON 

Declare @MyTable Table 
(
    SoNo VarChar (100), 
    SoItem VarChar (100), 
    SoRels VarChar (100), 
    LotSerial VarChar (100) 
) 

INSERT INTO @MyTable Values ('123456', '1', '001', 'ABCD') 
INSERT INTO @MyTable Values ('123456', '1', '001', 'AMOH') 
INSERT INTO @MyTable Values ('123456', '1', '001', 'POWK') 
INSERT INTO @MyTable Values ('123456', '1', '001', 'IUIL') 
INSERT INTO @MyTable Values ('123456', '1', '002', 'ABCE') 

SELECT 
    SoNo, 
    SoItem, 
    SoRels, 
    STUFF ((
     SELECT ', ' + LotSerial 
     FROM @MyTable T1 
     WHERE 1=1 
      AND T1.SoNo = T2.SoNo 
      AND T1.SoItem = T2.SoItem 
      And T1.SoRels = T2.SoRels 
     FOR XML PATH ('') 
    ), 1, 2, '') AS LotSerial 
FROM @MyTable T2 
GROUP BY SoNo, SoItem, SoRels 
+0

était FOR XML PATH disponible dans SQL Server 2000? –

+0

J'ai raté cette partie –

+0

Non, je ne pense pas que ce soit. Truc cool cependant. – HLGEM

Questions connexes