рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ, рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЛ рдПрдХ рд╕рд╛рде рдорд┐рд▓рд╛рдиреЗ рдХреЗ рдХрд╛рд░реНрдп рдЕрдХреНрд╕рд░ рд╕рд╛рдордиреЗ рдЖрддреЗ рд╣реИрдВред рдпрд╣ рдмрд╣реБрдд рджреБрдЦ рдХреА рдмрд╛рдд рд╣реИ, рд▓реЗрдХрд┐рди
рдЯреА-рдПрд╕рдХреНрдпреВрдПрд▓ рдорд╛рдирдХ
рдПрд╕рдпреВрдПрдо рдПрдХрддреНрд░реАрдХрд░рдг рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрджрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдХреЗ рд▓рд┐рдП рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ:
рдПрдордПрд╕рдЬреА 8117, рд╕реНрддрд░ 16, рд░рд╛рдЬреНрдп 1, рдкрдВрдХреНрддрд┐ 1
рдСрдкрд░реЗрдЯрд░ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдЪрд╛рд░ рд╕рдо рдСрдкрд░реЗрдЯрд░ рдХреЗ рд▓рд┐рдП рдЕрдорд╛рдиреНрдп рд╣реИредрдпрджреНрдпрдкрд┐ рдРрд╕реА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП,
MySQL рдХреЗ рд▓рд┐рдП
GROUP_CONCAT рдлрд╝рдВрдХреНрд╢рди рдФрд░
Oracle рдореЗрдВ
LISTAGG рдлрд╝рдВрдХреНрд╢рди рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рдерд╛ред рдмрджрд▓реЗ рдореЗрдВ,
SQL рд╕рд░реНрд╡рд░ рдореЗрдВ рдРрд╕реА
рдХреЛрдИ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдирд╣реАрдВ рд╣реИред
рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЖрдкрдХреЛ рдЗрд╕реЗ рдПрдХ рдЦрд╛рдореА рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ рд╕рдордЭрдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐
рдЯреА-рдПрд╕рдХреНрдпреВрдПрд▓ рдХреА рдХреНрд╖рдорддрд╛рдУрдВ рдХреЛ рдЕрдиреНрдп рдирд┐рд░реНрдорд╛рдгреЛрдВ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд▓рдЪреАрд▓реЗрдкрди рдХреЛ рдЕрдзрд┐рдХ рд▓рдЪреАрд▓реЗ рдФрд░ рдХреБрд╢рд▓рддрд╛ рд╕реЗ рдкреНрд░рджрд░реНрд╢рди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдорд┐рд▓рддреА рд╣реИ, рдЬрд┐рд╕ рдкрд░ рдмрд╛рдж рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреА рдЬрд╛рдПрдЧреАред
рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдореЗрдВ рдирд┐рдореНрди рддрд╛рд▓рд┐рдХрд╛ рд╕реЗ рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рдХрдИ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЛ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
IF OBJECT_ID('dbo.Chars', 'U') IS NOT NULL DROP TABLE dbo.Chars GO CREATE TABLE dbo.Chars ([Char] CHAR(1) PRIMARY KEY) INSERT INTO dbo.Chars ([Char]) VALUES ('A'), ('B'), ('C'), ('F'), ('D')
рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдмрд╕реЗ рд╕реНрдкрд╖реНрдЯ рд╕рдорд╛рдзрд╛рди рдХрд░реНрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИ:
DECLARE @Chars VARCHAR(100) , @Char CHAR(1) DECLARE cur CURSOR LOCAL READ_ONLY FAST_FORWARD FOR SELECT [Char] FROM dbo.Chars OPEN cur FETCH NEXT FROM cur INTO @Char WHILE @@FETCH_STATUS = 0 BEGIN SET @Chars = ISNULL(@Chars + ', ' + @Char, @Char) FETCH NEXT FROM cur INTO @Char END CLOSE cur DEALLOCATE cur SELECT @Chars
рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреНрд╡реЗрд░реА рдирд┐рд╖реНрдкрд╛рджрди рдХреА рджрдХреНрд╖рддрд╛ рдХреЛ рдХрдо рдХрд░рддрд╛ рд╣реИ рдФрд░, рдХрдо рд╕реЗ рдХрдо, рдмрд╣реБрдд рд╕реБрдВрджрд░ рдирд╣реАрдВ рджрд┐рдЦрддрд╛ рд╣реИред
рдЗрд╕рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рд╡реЗрд░рд┐рдПрдмрд▓ рдЕрд╕рд╛рдЗрди рдХрд░рдХреЗ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЛ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ:
DECLARE @Chars VARCHAR(100) SELECT @Chars = ISNULL(@Chars + ', ' + [Char], [Char]) FROM dbo.Chars SELECT @Chars
рдПрдХ рддрд░рдл, рдбрд┐рдЬрд╛рдЗрди рдмрд╣реБрдд рд╕рд░рд▓ рдирд┐рдХрд▓рд╛, рджреВрд╕рд░реА рддрд░рдл, рдПрдХ рдмрдбрд╝реЗ рдирдореВрдиреЗ рдкрд░ рдЗрд╕рдХрд╛ рдкреНрд░рджрд░реНрд╢рди рд╡рд╛рдВрдЫрд┐рдд рд╣реЛрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдХреБрдЫ рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИред
рдкрдВрдХреНрддрд┐ рдПрдХрддреНрд░реАрдХрд░рдг рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд┐рд░реНрдорд╛рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ
XML рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ:
SELECT Chars = STUFF(( SELECT ', ' + [Char] FROM dbo.Chars FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, '')
рдпрджрд┐ рдЖрдк рдпреЛрдЬрдирд╛ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк
рдореВрд▓реНрдп рдкрджреНрдзрддрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЙрдЪреНрдЪ рд▓рд╛рдЧрдд рдХреЛ рдиреЛрдЯрд┐рд╕ рдХрд░реЗрдВрдЧреЗ:

рдЗрд╕ рдСрдкрд░реЗрд╢рди рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк
XQuery рдЧреБрдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреНрд╡реЗрд░реА рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:
SELECT Chars = STUFF(CAST(( SELECT [text()] = ', ' + [Char] FROM dbo.Chars FOR XML PATH(''), TYPE) AS VARCHAR(100)), 1, 2, '')
рдирддреАрдЬрддрди, рд╣рдореЗрдВ рдПрдХ рдмрд╣реБрдд рд╣реА рд╕рд░рд▓ рдФрд░ рддреНрд╡рд░рд┐рдд рдирд┐рд╖реНрдкрд╛рджрди рдпреЛрдЬрдирд╛ рдорд┐рд▓рддреА рд╣реИ:

рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдПрдХ рдПрдХрд▓ рд╕реНрддрдВрдн рдкрд░ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕рдВрдШрдирди рдмрд╣реБрдд рдХрдард┐рдирд╛рдИ рдХрд╛ рдХрд╛рд░рдг рдирд╣реАрдВ рдмрдирддрд╛ рд╣реИред
рдПрдХ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рд╕реНрдерд┐рддрд┐ рдпрд╣ рд╣реИ рдХрд┐ рдЬрдм рдЖрдк рдПрдХ рд╕рд╛рде рдХрдИ рд╕реНрддрдВрднреЛрдВ рдкрд░ рд╕рдВрдШрдЯрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрди рддрд╛рд▓рд┐рдХрд╛ рд╣реИ:
IF OBJECT_ID('dbo.EntityValues', 'U') IS NOT NULL DROP TABLE dbo.EntityValues GO CREATE TABLE dbo.EntityValues ( EntityID INT , Value1 CHAR(1) , Value2 CHAR(1) ) CREATE NONCLUSTERED INDEX IX_WorkOut_EntityID ON dbo.EntityValues (EntityID) GO INSERT INTO dbo.EntityValues (EntityID, Value1, Value2) VALUES (1, 'A', 'X'), (2, 'B', 'Y'), (2, 'C', 'Z'), (2, 'F', 'H'), (1, 'D', 'R')
рдЬрд┐рд╕рдореЗрдВ рдЖрдк рдбреЗрдЯрд╛ рдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╕рдореВрд╣рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:

рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ, рдЖрдк
XML рдХреЙрд▓ рдХреЛ рдХреЙрдкреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рд╣рдореЗрдВ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд░реАрдб рдорд┐рд▓рддреЗ рд╣реИрдВ, рдЬреЛ рдХреНрд╡реЗрд░реА рдХреА рджрдХреНрд╖рддрд╛ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
SELECT ev.EntityID , Values1 = STUFF(CAST(( SELECT [text()] = ', ' + ev2.Value1 FROM dbo.EntityValues ev2 WHERE ev2.EntityID = ev.EntityID FOR XML PATH(''), TYPE) AS VARCHAR(100)), 1, 2, '') , Values2 = STUFF(CAST(( SELECT [text()] = ', ' + ev2.Value2 FROM dbo.EntityValues ev2 WHERE ev2.EntityID = ev.EntityID FOR XML PATH(''), TYPE) AS VARCHAR(100)), 1, 2, '') FROM ( SELECT DISTINCT EntityID FROM dbo.EntityValues ) ev
рдЗрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдпрджрд┐ рдЖрдк рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдпреЛрдЬрдирд╛ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ:

рдмрд╛рд░-рдмрд╛рд░ рдкрдврд╝рдиреЗ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдПрдХ рдЫреЛрдЯреА
XML рд╣реИрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
SELECT ev.EntityID , Values1 = STUFF(REPLACE( CAST([XML].query('for $a in /a return xs:string($a)') AS VARCHAR(100)), ' ,', ','), 1, 1, '') , Values2 = STUFF(REPLACE( CAST([XML].query('for $b in /b return xs:string($b)') AS VARCHAR(100)), ' ,', ','), 1, 1, '') FROM ( SELECT DISTINCT EntityID FROM dbo.EntityValues ) ev CROSS APPLY ( SELECT [XML] = CAST(( SELECT [a] = ', ' + ev2.Value1 , [b] = ', ' + ev2.Value2 FROM dbo.EntityValues ev2 WHERE ev2.EntityID = ev.EntityID FOR XML PATH('') ) AS XML) ) t
рд▓реЗрдХрд┐рди
рдХреНрд╡реЗрд░реА рд╡рд┐рдзрд┐ рдХреЗ рдмрд╛рд░-рдмрд╛рд░ рдХреЙрд▓ рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░рдг рдпрд╣ рдХреНрд╡реЗрд░реА рднреА рдЗрд╖реНрдЯрддрдо рдирд╣реАрдВ рд╣реЛрдЧреАред
рдЖрдк рдХрд░реНрд╕рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
IF OBJECT_ID('tempdb.dbo.#EntityValues') IS NOT NULL DROP TABLE #EntityValues GO SELECT DISTINCT EntityID , Values1 = CAST(NULL AS VARCHAR(100)) , Values2 = CAST(NULL AS VARCHAR(100)) INTO #EntityValues FROM dbo.EntityValues DECLARE @EntityID INT , @Value1 CHAR(1) , @Value2 CHAR(1) DECLARE cur CURSOR LOCAL READ_ONLY FAST_FORWARD FOR SELECT EntityID , Value1 , Value2 FROM dbo.EntityValues OPEN cur FETCH NEXT FROM cur INTO @EntityID , @Value1 , @Value2 WHILE @@FETCH_STATUS = 0 BEGIN UPDATE #EntityValues SET Values1 = ISNULL(Values1 + ', ' + @Value1, @Value1) , Values2 = ISNULL(Values2 + ', ' + @Value2, @Value2) WHERE EntityID = @EntityID FETCH NEXT FROM cur INTO @EntityID , @Value1 , @Value2 END CLOSE cur DEALLOCATE cur SELECT * FROM #EntityValues
рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЬреИрд╕рд╛ рдХрд┐ рдЕрднреНрдпрд╛рд╕ рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрдм рдмрдбрд╝реЗ
рдИрдЯреАрдПрд▓ рдкреИрдХреЗрдЬ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЙрдкрдпреЛрдЧреА рд╕рдорд╛рдзрд╛рди рдпреВрдкреАрдЖрдИ рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рдЪрд░ рдХреЛ рдЕрд╕рд╛рдЗрди рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИ:
IF OBJECT_ID('tempdb.dbo.#EntityValues') IS NOT NULL DROP TABLE #EntityValues GO DECLARE @Values1 VARCHAR(100) , @Values2 VARCHAR(100) SELECT EntityID , Value1 , Value2 , RowNum = ROW_NUMBER() OVER (PARTITION BY EntityID ORDER BY 1/0) , Values1 = CAST(NULL AS VARCHAR(100)) , Values2 = CAST(NULL AS VARCHAR(100)) INTO #EntityValues FROM dbo.EntityValues UPDATE #EntityValues SET @Values1 = Values1 = CASE WHEN RowNum = 1 THEN Value1 ELSE @Values1 + ', ' + Value1 END , @Values2 = Values2 = CASE WHEN RowNum = 1 THEN Value2 ELSE @Values2 + ', ' + Value2 END SELECT EntityID , Values1 = MAX(Values1) , Values2 = MAX(Values2) FROM #EntityValues GROUP BY EntityID
SQL рд╕рд░реНрд╡рд░ рдореЗрдВ
GROUP_CONCAT рдФрд░
LISTAGG рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдПрдирд╛рд▓реЙрдЧ рдирд╣реАрдВ рд╣реИред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ рд╕реНрдерд┐рддрд┐ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ, рдХреБрд╢рд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╕рдорд╛рд▓реЛрдЪрдирд╛ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рд╕реНрддрдХреНрд╖реЗрдк рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдкреЛрд╕реНрдЯ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдпрд╣ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдирд╛ рд╣реИред