【问题标题】:How to return dynamic columns from grouped values in SQL Server (Stored Procedure)如何从 SQL Server 中的分组值返回动态列(存储过程)
【发布时间】:2015-05-18 05:23:28
【问题描述】:

我有两个非常相似的案例需要生成 SP。

在第一种情况下,我需要一个能够按活动数量返回列的 SQL(如果可能的话是动态的)。我必须按 ActivityId 创建列。

案例 1:

日期、计数(ActivityId)

分组

返回列:Activity1、Activity2、Activity3

表 1

╔════════════╦══════════════╗
║ ActivityId ║ ActivityName ║
╠════════════╬══════════════╣
║          1 ║ Activity 1   ║
║          2 ║ Activity 2   ║
║          3 ║ Activity 3   ║
╚════════════╩══════════════╝

表 2

╔═══════════╦════════════╗
║   Date    ║ ActivityId ║
╠═══════════╬════════════╣
║ 1/05/2015 ║          1 ║
║ 1/05/2015 ║          1 ║
║ 2/05/2015 ║          2 ║
║ 3/05/2015 ║          3 ║
╚═══════════╩════════════╝

查询结果

╔═══════════╦═══════════╦═══════════╦═══════════╗
║   Date    ║ Activity1 ║ Activity2 ║ Activity3 ║
╠═══════════╬═══════════╬═══════════╬═══════════╣
║ 1/05/2015 ║         2 ║         0 ║         0 ║
║ 2/05/2015 ║         0 ║         1 ║         0 ║
║ 3/05/2015 ║         0 ║         0 ║         1 ║
╚═══════════╩═══════════╩═══════════╩═══════════╝

案例 2:

在另一种情况下,我将不得不做完全相同的事情,但不是 活动将是一个月中的几天列表:

表 1

╔════════════╦═══════════╦═══════╗
║    Date    ║ Account   ║ Value ║
╠════════════╬═══════════╬═══════╣
║ 30/05/2015 ║         1 ║    10 ║
║ 27/05/2015 ║         2 ║    40 ║
╚════════════╩═══════════╩═══════╝

查询结果:

╔═════════╦════════════╦════════════╦════════════╦════════════╦═════════════════════╗
║ Account ║ 30/05/2015 ║ 29/05/2015 ║ 28/05/2015 ║ 27/05/2015 ║…each day in a month ║
╠═════════╬════════════╬════════════╬════════════╬════════════╬═════════════════════╣
║       1 ║         10 ║          0 ║          0 ║          0 ║                     ║
║       2 ║          0 ║          0 ║          0 ║         40 ║                     ║
╚═════════╩════════════╩════════════╩════════════╩════════════╩═════════════════════╝

【问题讨论】:

标签: sql sql-server tsql


【解决方案1】:

对于案例 1,试试这个:

--Creating Test tables
create table #activity
(
    ActivityId TINYINT,
    ActivityName VARCHAR(20)
)

create table #date
(
    [Date] DATE,
    ActivityId TINYINT
)

INSERT INTO #activity VALUES(1,'Activity 1')
INSERT INTO #activity VALUES(2,'Activity 2')
INSERT INTO #activity VALUES(3,'Activity 3')

INSERT INTO #date VALUES('2015-05-01',1)
INSERT INTO #date VALUES('2015-05-01',1)
INSERT INTO #date VALUES('2015-05-02',2)
INSERT INTO #date VALUES('2015-05-03',3)


DECLARE @activities NVARCHAR(MAX)
DECLARE @stmt NVARCHAR(MAX)

SET  @activities = ''
SET  @stmt = ''

--Get List of Activities
SELECT  @activities = @activities + ',[' + ActivityName + ']'
FROM    #activity

SET @activities = RIGHT(@activities, LEN(@activities)-1) --Remove Leading Comma

--Build PIVOT Statement
SET @stmt = 'SELECT  [Date],' + @activities + '
            FROM    (SELECT d.[Date], a.ActivityName
                     FROM   #date d
                            INNER JOIN #activity a ON d.ActivityId = a.ActivityId) tab
                    PIVOT (COUNT(ActivityName) FOR ActivityName IN (' + @activities + ')) AS NumberOfActivities'

--Execute
EXEC sp_executesql @stmt

--CleanUp
DROP TABLE #activity
DROP TABLE #date

【讨论】:

  • 对于案例 2,您可以采用相同的方法,只需更改在我的示例中称为“tab”的语句中的查询,而不是 @activities 字符串,您可以构建一个字符串来约束您的日期想要显示...希望这有帮助!
【解决方案2】:

我可以使用 PIVOT 命令来做到这一点:

案例 1

select p.[Date], ISNULL([1],0)[Activity1], ISNULL([2],0)[Activity2], ISNULL([3],0)[Activity3], ISNULL([4],0)[Activity4], ISNULL([5],0)[Activity5], ISNULL([6],0)[Activity6] 
FROM
(
    SELECT CONVERT(date, [Date]) [Date], ActivityId, COUNT(*) Total
    from Activity
    group by convert(date, [Date]), ActivityId

) AS Tb

PIVOT
(
    SUM(Total)
    FOR ActivityId IN ([1],[2],[3],[4],[5],[6])
) p
order by convert(date, p.[Date])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-11
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多