2017-03-15 39 views
1

我有一個表table1這樣的:結合多行和列在SQL Server

sl next day count status 
-------------------------- 
A 1  1 1 Yes 
A 1  1 2 Yes 
A 1  1 3 Yes 
A 1  1 4 Yes 

A 1  2 1 Yes 
A 1  2 2 No 
A 1  2 3 Yes 
A 1  2 4 Yes 

A 2  1 1 Yes 
A 2  1 2 Yes 
A 2  1 3 Yes 
A 2  1 4 Yes 

和輸出應該是這樣的:

sl next status daylist 
------------------------------ 
A 1  Yes  1-All 
        2-1,3,4 

A 1  No  2-2 

A 2  Yes  1-All 

正如你看到的輸出,daylist是組合計數和日期,按/next分組。

任何人都可以幫助我在T-SQL中實現這一點嗎?

在此先感謝!

+1

你能解釋一下這個輸出?你在這裏試圖做什麼並不完全清楚。 –

+2

看起來像這樣會在表示層處理(在你的應用程序中),但是不管你想要實現什麼,都是超級混淆。 – scsimon

回答

3

這種事情應該在應用程序層而不是sql中完成。

使用stuff() with select ... for xml path ('') method of string concatenationcommon table expression兩步串聯:

with cte as (
    select 
     sl 
    , next 
    , status 
    , day 
    , daylist = stuff((
     select 
      ','+convert(varchar(10),i.count) 
     from t as i 
     where t.status = i.status 
      and t.day = i.day 
      and t.next = i.next 
     order by i.count 
     for xml path (''), type).value('.','varchar(max)') 
     ,1,1,'')  
    from t 
    group by sl, next, status, day 
) 
select 
    sl 
    , next 
    , status 
    , daylist = stuff((
     select 
      char(10)+convert(varchar(10),day)+'-'+i.daylist 
     from cte as i 
     where cte.status = i.status 
     and cte.next = i.next 
     order by i.day 
     for xml path (''), type).value('.','varchar(max)') 
     ,1,1,'')  
from cte 
group by sl, next, status 
order by next, status desc 

rextester演示:http://rextester.com/FQE41002

回報:

+----+------+--------+-----------+ 
| sl | next | status | daylist | 
+----+------+--------+-----------+ 
| A | 1 | Yes | 1-1,2,3,4 | 
| |  |  | 2-1,3,4 | 
| A | 1 | No  | 2-2  | 
| A | 2 | Yes | 1-1,2,3,4 | 
+----+------+--------+-----------+ 
+0

謝謝SqlZim先生。它也很好看。但是,在daylist中新的換行符在我使用的CHAR(10)中不適用於我。 – cgsabari

1
Declare @YourTable table (sl varchar(10),next int,day int,count int, status varchar(10)) 
Insert Into @YourTable values 
('A' ,1 ,1 ,1 ,'Yes'), 
('A' ,1 ,1 ,2 ,'Yes'), 
('A' ,1 ,1 ,3 ,'Yes'), 
('A' ,1 ,1 ,4 ,'Yes'), 
('A' ,1 ,2 ,1 ,'Yes'), 
('A' ,1 ,2 ,2 ,'No'), 
('A' ,1 ,2 ,3 ,'Yes'), 
('A' ,1 ,2 ,4 ,'Yes'), 
('A' ,2 ,1 ,1 ,'Yes'), 
('A' ,2 ,1 ,2 ,'Yes'), 
('A' ,2 ,1 ,3 ,'Yes'), 
('A' ,2 ,1 ,4 ,'Yes') 


Select sl  = IIF(Lag(concat(sl,next,status),1) over (Order by RN)=concat(sl,next,status),'',sl) 
     ,next = IIF(Lag(concat(sl,next,status),1) over (Order by RN)=concat(sl,next,status),'',cast(next as varchar(25))) 
     ,status = IIF(Lag(status,1) over (Order by RN)=status,'',status) 
     ,daylist = concat(day,'-',iif(rowCnt=maxRow,'All',string)) 
From (
     Select *,RN = Row_Number() over (Order by sl,next,day,status desc) 
     From (
       Select sl,Next,Status,Day,rowCnt=count(*) 
       From @YourTable 
       Group By sl,Next,Status,Day 
       ) A 
     Cross Apply (Select maxRow=count(*) From @YourTable Where sl=A.sl and next=A.next and day=A.day) C 
     Cross Apply (
         Select String = Stuff((Select ',' +cast(count as varchar(25)) 
               From @YourTable 
               Where sl=A.sl and next=A.next and day=A.day and status=A.status 
               For XML Path ('')),1,1,'') 
        ) B 
    ) A 
Order By RN 

返回

sl next status daylist 
A 1  Yes  1-All 
        2-1,3,4 
A 1  No  2-2 
A 2  Yes  1-All 
+0

謝謝約翰先生。它按預期工作。 – cgsabari

+0

@cgsabari快樂它幫助 –

0
DECLARE @tb TABLE(sl VARCHAR(2),[next] INT,[day] INT ,[count] INT,status VARCHAR(3)) 
INSERT INTO @tb 
SELECT 'A',1,1,1,'Yes' UNION ALL 
SELECT 'A',1,1,2,'Yes' UNION ALL 
SELECT 'A',1,1,3,'Yes' UNION ALL 
SELECT 'A',1,1,4,'Yes' UNION ALL 

SELECT 'A',1,2,1,'Yes' UNION ALL 
SELECT 'A',1,2,2,'No' UNION ALL 
SELECT 'A',1,2,3,'Yes' UNION ALL 
SELECT 'A',1,2,4,'Yes' UNION ALL 

SELECT 'A',2,1,1,'Yes' UNION ALL 
SELECT 'A',2,1,2,'Yes' UNION ALL 
SELECT 'A',2,1,3,'Yes' UNION ALL 
SELECT 'A',2,1,4,'Yes' 

SELECT sl,[next],[status] ,LTRIM(t.[day])+'-'+STUFF(c.s,1,1,'') AS daylist 
FROM @tb AS t 
CROSS APPLY(
     SELECT CASE WHEN a.OtherStatusCnt>0 THEN 
        CASE WHEN a.[status]=t.[status] THEN ','+LTRIM(a.[count]) ELSE '' END 
      ELSE 
        CASE WHEN a.id=1 THEN '.All' ELSE '' END 
      END 
     FROM (
      SELECT tt.count,tt.[status] 
       ,COUNT(CASE WHEN tt.[status]!=t.[status] THEN 1 ELSE NULL END)OVER() AS OtherStatusCnt 
       ,ROW_NUMBER()OVER(ORDER BY tt.[count]) AS id 
      FROM @tb AS tt WHERE tt.sl=t.sl AND tt.[next]=t.[next] AND tt.[day]=t.[day] 
    ) AS a 
     FOR XML PATH('') 
) c(s) 
GROUP BY sl,[next],[day],[status],c.s 
ORDER BY sl,[next],[status] desc 
 
sl next  status daylist 
---- ----------- ------ --------- 
A 1   Yes 1-All 
A 1   Yes 2-1,3,4 
A 1   No  2-2 
A 2   Yes 1-All