2011-07-05 16 views
20

Załóżmy, że mam tej tabeli [Tabela1]Jak złączyć wszystkie ciągi z pewnej kolumny dla każdej grupy

Name Mark 
------- ------ 
ABC  10 
DEF  10 
GHI  10 
JKL  20 
MNO  20 
PQR  30 

Jaki powinien być mój instrukcję SQL, aby pobrać rekord, który wygląda tak: (grupa według [ znak]). mam zrobić z 1 i 2 kolumny, ale nie wiem jak osiągnąć trzecią kolumnę (concat [nazwa] z tym samym znakiem [])

mark count  names 
---- -----  ----------- 
10  3  ABC,DEF,GHI 
20  2  JKL,MNO 
30  1  PQR 

Używam Microsoft SQL. Proszę o pomoc. Dzięki

+0

Jakiego DBMS używasz? –

+0

Microsoft SQL. Przepraszamy za nieuwzględnienie tej informacji. – yonan2236

+0

Zobacz także http://stackoverflow.com/questions/451415/simulating-group-concat-mysql-function-in-ms-sql-server-2005 –

Odpowiedz

35

Jeśli MS SQL 2005 lub nowszy.

declare @t table([name] varchar(max), mark int) 

insert @t values ('ABC', 10), ('DEF', 10), ('GHI', 10), 
    ('JKL', 20), ('MNO', 20), ('PQR', 30) 


select t.mark, COUNT(*) [count] 
    ,STUFF((
     select ',' + [name] 
     from @t t1 
     where t1.mark = t.mark 
     for xml path(''), type 
    ).value('.', 'varchar(max)'), 1, 1, '') [values] 
from @t t 
group by t.mark 

wyjściowa:

mark  count  values 
----------- ----------- -------------- 
10   3   ABC,DEF,GHI 
20   2   JKL,MNO 
30   1   PQR 
+1

+1 dla ścieżki xml ('') – Pankaj

+0

Nie robi różnicy, gdy nie pisze [wartości]? – Pankaj

+0

@ SQL, to tylko alias, więc bez względu na numer: –

1

rozwiązanie polishchuks jest bardziej elegancki, ale jest to w zasadzie to samo, po prostu do czynienia z tylnym przecinek inaczej.

CREATE TABLE #Marks(Name nchar(3), Mark int) 

INSERT INTO #Marks 

SELECT 'ABC', 10 UNION ALL 
SELECT 'DEF', 10 UNION ALL 
SELECT 'GHI', 10 UNION ALL 
SELECT 'JKL', 20 UNION ALL 
SELECT 'MNO', 20 UNION ALL 
SELECT 'PQR', 30 


SELECT 
    mark, 
    [count], 
    CASE WHEN Len(Names) > 0 THEN LEFT(Names, LEN(Names) -1) ELSE '' END names 
    FROM 
(
SELECT 
    Mark, 
    COUNT(Mark) AS [count], 
     (
     SELECT DISTINCT 
      Name + ', ' 
     FROM 
      #Marks M1 
     WHERE M1.Mark = M2.Mark 
     FOR XML PATH('')  
     ) Names 
FROM #Marks M2 
GROUP BY Mark 
) M 
+0

Nie jestem pewien, czy potrzebujesz pierwszej odrębnej klauzuli w pierwszym podzapytaniu, gdy robisz grupę według znaku, popraw mnie, jeśli się mylę ... – Ram

+0

tak, nie potrzebujesz tego – woggles

0

Luźno oparte na Itzik Ben-Gan, Wewnątrz Microsoft SQL Server 2005: Programowanie T-SQL, p. 215:

IF OBJECT_ID('dbo.Table1') IS NOT NULL 
    DROP TABLE dbo.Table1 ; 
GO 
CREATE TABLE dbo.Table1 (Name VARCHAR(10), Mark INT) ; 

INSERT INTO dbo.Table1 (Name, Mark) VALUES ('ABC',  10) ; 
INSERT INTO dbo.Table1 (Name, Mark) VALUES ('DEF',  10) ; 
INSERT INTO dbo.Table1 (Name, Mark) VALUES ('GHI',  10) ; 
INSERT INTO dbo.Table1 (Name, Mark) VALUES ('JKL',  20) ; 
INSERT INTO dbo.Table1 (Name, Mark) VALUES ('MNO',  20) ; 
INSERT INTO dbo.Table1 (Name, Mark) VALUES ('PQR',  30) ; 


WITH DelimitedNames AS 
(
    SELECT Mark, T2.Count, 
     ( SELECT Name + ',' AS [text()] 
      FROM dbo.Table1 AS T1 
      WHERE T1.Mark = T2.Mark 
      ORDER BY T1.Mark 
      FOR XML PATH('')) AS Names 
    FROM (SELECT Mark, COUNT(*) AS Count FROM dbo.Table1 GROUP BY Mark) AS T2 
) 
SELECT Mark, Count, LEFT(Names, LEN(NAMES) - 1) AS Names 
FROM DelimitedNames ; 
Powiązane problemy