使用SQL Server将多行合并为一行?

时间:2017-08-05 06:47:52

标签: sql-server

我想使用SQL Server中的存储过程合并我的通知数据。我已经编写了查询,但是在这个查询中,我获得的不仅仅是多行中的用户数据。

我想合并关注者通知。喜欢"用户跟随用户b然后用户b"得到通知,例如"用户a开始关注你"。再次"用户c关注用户b"然后"用户b再次收到类似" "用户c关注你"。

再次"用户d再次关注用户b,然后用户b再次关注获取通知"。但是现在我想像这个通知那样合并"用户a,b和1个用户开始关注你"。

这是我的存储过程:

SELECT 
    N.NotificationId,
    N.UserId,
    N.ActionUserId,
    (CASE WHEN N.NotificationTypeId = 1 THEN 1
          WHEN N.NotificationTypeId = 7 THEN 3
        ELSE    
             2
    END) AS TypeId,                         
    AU.ProfileImage,
    AU.UserName,
    N.IsRead,
    (CASE WHEN N.NotificationTypeId = 1 THEN 1
        WHEN N.NotificationTypeId = 7 THEN 3
      ELSE 2
    END) AS TypeId,         
    N.NotificationTypeId,
    N.InsertDateTime
FROM 
    Notifications N
INNER JOIN 
    Users U ON N.UserId = U.UserId
INNER JOIN 
    Users AU ON N.ActionUserId = AU.UserId      
ORDER BY 
    N.InsertDateTime DESC

这是我目前的o / p =>

  NotificationId | UserId | ActionUserId | UserName | NotificationTypeId | InsertDateTime            | ProfileImage 
  6                20        15             hbc        1                    2017-06-22 17:14:16.803    20170416032403869.jpeg
  5                20        16             tyu        1                    2017-06-22 17:12:12.297     20170416031522534.jpeg
  4                20        17             opl        1                    2017-06-22 17:11:58.060     20170416031250102.jpeg
  3                10        11             abc        1                    2017-06-22 16:14:16.803    20170416032403867.jpeg
  2                10        12             xyz        1                    2017-06-22 16:14:12.297     20170416031522533.jpeg
  1                10        13             rty        1                    2017-06-22 16:13:58.060     20170416031250101.jpeg

这是我的例外情况o / p =>

 NotificationId | UserId | ActionUserId | UserName | NotificationTypeId | InsertDateTime            | ProfileImage           | NotificationText
   6                20        15             hbc        1                    2017-06-22 17:14:16.803    20170416032403869.jpeg    hbc,tyu and 1  other users followed you
   3                10        11             abc        1                    2017-06-22 16:14:16.803    20170416032403867.jpeg    abc,xyz and 1  other users followed you

创建测试数据=>

declare @Notifications table(NotificationID int, UserID int, ActionUserID int, NotificationTypeID int, InsertDateTime datetime);
declare @Users table(UserID int, UserName nvarchar(10), ProfileImage nvarchar(50))
insert into @Notifications values (6,20,15,1,'2017-06-22 17:14:16.803'),(5,20,16,1,'2017-06-22 17:12:12.297'),(4,20,17,1,'2017-06-22 17:11:58.060'),(3,10,11,1,'2017-06-22 16:14:16.803'),(2,10,12,1,'2017-06-22 16:14:12.297'),(1,10,13,1,'2017-06-22 16:13:58.060');
insert into @Users values (15,'hbc','20170416032403869.jpeg'),(16,'tyu','20170416031522534.jpeg'),(17,'opl','20170416031250102.jpeg'),(10,'aaa',''),(11,'abc','20170416032403867.jpeg'),(12,'xyz','20170416031522533.jpeg'),(13,'rty','20170416031250101.jpeg');

1 个答案:

答案 0 :(得分:2)

试试这个:

declare @Notifications table
(NotificationID int, 
UserID int, 
ActionUserID int, 
NotificationTypeID int, 
InsertDateTime datetime);
declare @Users table
(UserID int, 
UserName nvarchar(10), 
ProfileImage nvarchar(50))

insert into @Notifications values 
(6,20,15,1,'2017-06-22 17:14:16.803'),
(5,20,16,1,'2017-06-22 17:12:12.297'),
(4,20,17,1,'2017-06-22 17:11:58.060'),
(3,10,11,1,'2017-06-22 16:14:16.803'),
(2,10,12,1,'2017-06-22 16:14:12.297'),
(1,10,13,1,'2017-06-22 16:13:58.060');
insert into @Users values (15,'hbc','20170416032403869.jpeg'),
(16,'tyu','20170416031522534.jpeg'),
(17,'opl','20170416031250102.jpeg'),
(10,'aaa',''),
(20,'bbb',''),
(11,'abc','20170416032403867.jpeg'),
(12,'xyz','20170416031522533.jpeg'),
(13,'rty','20170416031250101.jpeg');


declare @followCount table
(
userid int,
cnt int
)

INSERT INTO @followCount
select N.UserID, count(*) 
FROM
    @Notifications N
INNER JOIN 
    @Users U ON N.UserId = U.UserId
INNER JOIN 
    @Users AU ON N.ActionUserId = AU.UserId 
GROUP BY n.UserID

declare @msg table
(
userid int,
NotificationMsg varchar(15)
)
INSERT INTO @msg
SELECT DISTINCT N.UserID, Stuff((SELECT ', ' + UserName  
                FROM
(SELECT UserID, UserName FROM (SELECT N.UserId,
    AU.UserName,
    ROW_NUMBER() OVER (PARTITION BY N.UserID ORDER BY N.InsertDateTime DESC) as rn
    FROM
    @Notifications N
INNER JOIN 
    @Users U ON N.UserId = U.UserId
INNER JOIN 
    @Users AU ON N.ActionUserId = AU.UserId
INNER JOIN 
    @followCount C on C.userid = N.UserID) t2 WHERE rn < 3) t2
    WHERE  t2.UserID  = N.UserID  
                FOR XML PATH('')), 1, 2, '') AS NotificationMsg
FROM @Notifications N

; with cte as    
(SELECT N.NotificationId,
        N.UserId,
        N.ActionUserId,
        (CASE WHEN N.NotificationTypeId = 1 THEN 1
            WHEN N.NotificationTypeId = 7 THEN 3
        ELSE    
             2
        END) AS TypeId,                         
        AU.ProfileImage,
        AU.UserName,
        N.NotificationTypeId,
        N.InsertDateTime,
        m.NotificationMsg + CASE WHEN c.cnt > 2 THEN ' + ' 
        + FORMAT(c.cnt - 2, '0') + ' other users' END + ' followed you.' AS NotificationText,
        ROW_NUMBER() OVER (PARTITION BY N.UserID ORDER BY N.InsertDateTime DESC) as rn
FROM 
    @Notifications N
INNER JOIN 
    @Users U ON N.UserId = U.UserId
INNER JOIN 
    @Users AU ON N.ActionUserId = AU.UserId
INNER JOIN 
    @followCount C on C.userid = N.UserID 
INNER JOIN @msg M ON m.userid = N.UserID)

SELECT NotificationID, UserID, ActionUserID, UserName, 
NotificationTypeID, InsertDateTime, ProfileImage, NotificationText 
FROM  cte WHERE rn = 1

请注意我必须为用户标识20添加一个条目。您提供的示例数据只生成一条记录。

使得它特别棘手的是,需要两个名字加上x个其他名字。这涉及几个中间步骤。很可能是一个比SQL更专业的人可以缩短它。另请注意,我只测试了这些数据。你需要检查更多和少于3个其他用户的数字,以确保它仍然是好的。