我有以下脚本:
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
这会产生如下所示的输出:
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
我想通过SoNo,SoItem,SoRels进行分组并获取每个LotSerial的列表。所以,我的输出看起来像这样:
SoNo So Item SoRels LotSerial
123456 1 001 ABCD, AMOH, POWK, IUIL
123456 1 002 ABCE
我需要这样做,我可以将此信息提取回基于SoNo,SoItem,SoRels的主查询。
非常感谢任何帮助。
答案 0 :(得分:5)
一如既往,尽可能避免使用游标。您的场景非常适合用户定义的功能。我为这个例子简化了你的模式。本质上,我们将与逗号匹配的序列连接到用户定义函数中的变量,然后重新调整结果。如果可以使用Null值,则可能需要添加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
结果 ABCD,EFGH,IJKL
答案 1 :(得分:2)
@cmsjr beat me to it with his answer这也是一样的。我以不同的方式构建字符串,并有一个完整的工作示例。
试试这个:
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 SoNo=@SoNo AND SoItem=@SoItem AND SoRels=@SoRels
RETURN @cvs
END
go
SELECT
SoNo, SoItem, SoRels, dbo.LotSerial_to_CVS(SoNo, SoItem, SoRels)
FROM YourTable
GROUP BY SoNo, SoItem, SoRels
输出:
SoNo SoItem SoRels
----------- ----------- ------ -----------------------
123456 1 001 ABCD, AMOH, POWK, IUIL
123456 1 002 ABCE
(2 row(s) affected)
答案 2 :(得分:1)
几乎任何情况下都不需要光标。
您也可以使用XML PATH执行相同的操作。这是一个工作样本:
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