创建一个存储过程来聚合行

时间:2018-08-25 15:39:07

标签: sql-server azure stored-procedures aggregate

具有包含以下行的交易表:

Id    UserId   PlatformId    TransactionTypeId
-------------------------------------------------
 0       1          3                1
 1       1          1                2
 2       2          3                2
 3       3          2                1
 4       2          3                1

如何编写一个存储过程,该存储过程可以将行聚合为具有以下格式的新表?

Id    UserId   Platforms          TransactionTypeId
-------------------------------------------------
 0      1      {"p3":1,"p1":1}    {"t1":1,"t2":1}
 1      2      {"p3":2}           {"t2":1,"t1":1}
 3      3      {"p2":1}           {"t1":1}

因此,这些行将由用户汇总,计算每个平台/ transactionType并存储为键/值json字符串。

参考:My previous related question

2 个答案:

答案 0 :(得分:1)

您可以使用GROUP BYFOR JSON

SELECT MIN(ID) AS ID, UserId, MIN(sub.x) AS Platforms, MIN(sub2.x) AS Transactions
FROM tab t
OUTER APPLY (SELECT CONCAT('p', platformId) AS platform, cnt 
            FROM (SELECT PlatformId, COUNT(*) AS cnt
                  FROM tab t2 WHERE t2.UserId = t.UserId  
                  GROUP BY PlatformId) s
              FOR JSON AUTO) sub(x)
OUTER APPLY (SELECT CONCAT('t', TransactiontypeId) AS Transactions, cnt 
            FROM (SELECT TransactiontypeId, COUNT(*) AS cnt
                  FROM tab t2 WHERE t2.UserId = t.UserId  
                  GROUP BY TransactiontypeId) s
              FOR JSON AUTO) sub2(x)
GROUP BY UserId;

DBFiddle Demo

结果有点不同(键值数组),但请以起点为准。

答案 1 :(得分:1)

您的示例JSON并不是真正的json,但由于您希望这样做:

SELECT u.UserId, plt.pValue, ttyp.ttValue
FROM Users AS [u]
CROSS APPLY (
SELECT '{'+STUFF( (SELECT ',"'+pn.pName+'":'+LTRIM(STR(pn.pCount))
    FROM (SELECT p.Name AS pName, COUNT(*) AS pCount 
        FROM transactions t
        left JOIN Platforms p ON p.PlatformID = t.PlatformId
        WHERE t.UserId = u.UserId
        GROUP BY p.PlatformId, p.Name
        ) pn
    FOR XML PATH('')),1,1,'')+'}'
    ) plt(pValue)
CROSS APPLY (
SELECT '{'+STUFF( (SELECT ',"'+tty.ttName+'":'+LTRIM(STR(tty.ttCount))
    FROM (SELECT tt.Name AS ttName, COUNT(*) AS ttCount 
        FROM transactions t
        left JOIN dbo.TransactionType tt ON tt.TransactionTypeId = t.TransactionTypeID
        WHERE t.UserId = u.UserId
        GROUP BY tt.TransactionTypeId, tt.Name
        ) tty
    FOR XML PATH('')),1,1,'')+'}'
    ) ttyp(ttValue)
WHERE EXISTS (SELECT * FROM transactions t WHERE u.UserId = t.UserId)
ORDER BY UserId;

DBFiddle Sample