How to collect data to single row in sql server

六眼飞鱼酱① 提交于 2020-01-03 07:03:09

问题


I have table Risks and history table Risks_history. In Risks table i have data like below:

-----------------------------
| ID | DealID | Description |
-----------------------------
| 1  | 14     | Risk1       |
-----------------------------
| 2  | 14     | Risk2       |
-----------------------------
| 3  | 14     | Risk3       |
-----------------------------
| 4  | 15     | Risk4       |
-----------------------------

So here is we can see that one deal can have several Risks. I need to save data of table Risks in history like below:

-------------------------------------
| ID | dealID |   AllDescriptions   |   
-------------------------------------
| 1  | 14     | Risk1, Risk2, Risk3 |
-------------------------------------
| 2  | 15     | Risk4               |
-------------------------------------

I need trigger that will do it. But now I cant.

How I can collect data from several rows into one row?

EDIT:

I need trigger, so now i have below trigger:

      INSERT INTO [dbo].[Risks_history]
      (
            DealID,
            [AllDescription]
      )
      SELECT 
            [DealID],
            stuff((select ',' + i.name from inserted i
                   where i.DealID= i2.DealID
                   FOR XML PATH('')),1,1,'') as Description                                          
        FROM inserted i2;

But in table Risks_history i have data(which trigger wrote) like below:

 - When I change Risk1:

    -------------------------------------
    | ID | dealID |   AllDescriptions   |   
    -------------------------------------
    | 1  | 14     | Risk1, Risk1, Risk1 |
    -------------------------------------

 - When I change Risk2:

-------------------------------------
| ID | dealID |   AllDescriptions   |   
-------------------------------------
| 1  | 14     | Risk2, Risk2, Risk2 |
-------------------------------------

 - When I change Risk3:

-------------------------------------
| ID | dealID |   AllDescriptions   |   
-------------------------------------
| 1  | 14     | Risk3, Risk3, Risk3 |
-------------------------------------

But I need to write all Risks whatever risk changing


回答1:


Please try this..

SELECT DISTINCT
      DealID
    , STUFF((
        SELECT N', ' + CAST([Description] AS VARCHAR(4000))
        FROM Risks R2
        WHERE R1.DealID = R2.DealID
        FOR XML PATH (''), TYPE), 1, 2, '') AS AllDescriptions   
FROM Risks R1
GROUP BY DealID

Your modified trigger and assuming DealID and Description are column names of Risks tables,

DECLARE @DealID INT;

SELECT 
    @DealID = [DealID]                                         
FROM inserted;

INSERT INTO [dbo].[Risks_history]
      (
            DealID,
            [AllDescription]
      )
      SELECT 
            [DealID],
            STUFF((
                SELECT ', ' + R2.[Description]
                FROM Risks R2
                WHERE R1.DealID = R2.DealID
                FOR XML PATH (''), TYPE), 1, 2, '') AS AllDescriptions                                        
        FROM Risks R1
        WHERE DealID = @DealID
    GROUP BY DealID



回答2:


Try this,

SELECT 
  ID,
  STUFF((
    SELECT ', '  + CAST(Description AS VARCHAR(MAX)) 
    FROM Risks
    WHERE (ID = RiskMain.ID) 
FOR XML PATH (''), TYPE), 1, 2, '') AS AllDescriptions  
FROM Risks RiskMain
GROUP BY ID



回答3:


create table #c

( ID int, DealID int, Description varchar(10))
insert into #c values
(1,14,'Risk1'),
(2,14,'Risk2'),
(3,14,'Risk3'),
(4,15,'Risk4')

SELECT DISTINCT DealID,
                STUFF((SELECT ','+Description   
                       FROM #c t1 
                       WHERE t1.DealID = t2.DealID 
                        FOR XML PATH(''))
                       ,1,1,'') as Description   
FROM #c t2



回答4:


DECLARE @tblTest AS TABLE
 (
   ID  INT,
   DealID INT,
   Description VARCHAR(50)
 )  

 INSERT INTO @tblTest VALUES(1,14,'Risk1')
 ,(2,14,'Risk2')
 ,(3,14,'Risk3')
 ,(4,15,'Risk4')

 SELECT STUFF((SELECT distinct ',' + QUOTENAME(Description) 
            FROM @tblTest c
            --WHERE c.DealID=T.DealID   
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

 SELECT
    ROW_NUMBER() OVER (ORDER BY MAX(T.ID)) AS ID,
    T.DealID,
    (SELECT STUFF((SELECT distinct ',' + Description 
            FROM @tblTest c
            WHERE c.DealID=T.DealID 
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')) AS AllDescriptions
FROM @tblTest T
GROUP BY T.DealID



回答5:


You can get this output with one single SQL query like this:

SELECT t1.DealID,
Descriptions =REPLACE( (SELECT Description AS [data()]
FROM Risks_history t2
WHERE t2.DealID = t1.DealID
ORDER BY Description
FOR XML PATH('')
), ' ', ',')
FROM Risks_history t1
GROUP BY DealID ;

Now you have to put this query under the trigger to insert filter data into your table.




回答6:


We can use MIN in the ID and DealID in GROUP BY:

SELECT MIN(u.ID) AS ID, 
    u.DealID,
    STUFF((SELECT ', ' + A.Description FROM Mytable A
    WHERE A.DealID=u.DealID FOR XML PATH('')),1,1,'') As [Description]
FROM Mytable u
GROUP BY u.DealID


来源:https://stackoverflow.com/questions/40152481/how-to-collect-data-to-single-row-in-sql-server

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!