Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL定义一组列,然后将行数据透视到这些列_Sql_Sql Server_Sql Server 2008_Tsql - Fatal编程技术网

SQL定义一组列,然后将行数据透视到这些列

SQL定义一组列,然后将行数据透视到这些列,sql,sql-server,sql-server-2008,tsql,Sql,Sql Server,Sql Server 2008,Tsql,我有一个数据表,显示了人们获得某个分数的周数(见更新中的DDL/DML) 我希望我的查询将一周中的52天定义为单独的列,然后在相应的周数列下面列出一个人的标记 结果会是这样的: | PersonId | Week 1 | Week 2 | Week 3 | Week 4 | Week 5 | Week 6 | Week 7 | Week 8 | etc... |----------|--------|--------|--------|--------|--------|--------|---

我有一个数据表,显示了人们获得某个分数的周数(见更新中的DDL/DML)

我希望我的查询将一周中的52天定义为单独的列,然后在相应的周数列下面列出一个人的标记

结果会是这样的:

| PersonId | Week 1 | Week 2 | Week 3 | Week 4 | Week 5 | Week 6 | Week 7 | Week 8 | etc...
|----------|--------|--------|--------|--------|--------|--------|--------|--------| etc...
|    1     |    P   |    P   |    P   |    P   |    P   |  Null  |  Null  |  Null  | etc...
|    2     |    P   |    X   |    X   |    P   |    P   |  Null  |  Null  |  Null  | etc...
我曾考虑尝试一个
透视图
,但我不认为这会起作用,因为行数据不一定有我想要的完整的52周列标题

如果一周没有分数,我很高兴周数列下的分数为空,但查询本身必须显示第1周到第52周的列

我想做的事可能吗

更新:根据要求更新DDL和DML

CREATE TABLE mytable
    ([Id] int, [PersonId] int, [Mark] varchar(2), [Week] int)
;

INSERT INTO mytable
    ([Id], [PersonId], [Mark], [Week])
VALUES
    (1, 1, 'P', 1),
    (2, 1, 'P', 2),
    (3, 1, 'P', 3),
    (4, 1, 'P', 4),
    (5, 1, 'P', 5),
    (1, 2, 'P', 1),
    (2, 2, 'X', 2),
    (3, 2, 'X', 3),
    (4, 2, 'P', 4),
    (5, 2, 'P', 5)
;

您可以通过一个日历表来实现这一点。在我的大多数数据库中,我通常都有一个物理表,其中可以包含周数(特别是因为一些企业可能会以稍微不同的方式处理这些周数-是星期三,1月1日第1周还是前一年第52周?),业务季度,假期,或者特定企业可能需要的任何其他内容

您还可以使用虚拟表执行此操作,如图所示。当然,您需要将周数扩展到52周

SELECT
    PersonID, [Week 1], [Week 2], [Week 3], [Week 4], [Week 5]
FROM
    (
        SELECT
            MT.PersonID, MT.Mark, CAL.WeekNumberName
        FROM
            (
                SELECT 1 AS WeekNumber, 'Week 1' AS WeekNumberName
                UNION ALL
                SELECT 2 AS WeekNumber, 'Week 2' AS WeekNumberName
                UNION ALL
                SELECT 3 AS WeekNumber, 'Week 3' AS WeekNumberName
                UNION ALL
                SELECT 4 AS WeekNumber, 'Week 4' AS WeekNumberName
                UNION ALL
                SELECT 5 AS WeekNumber, 'Week 5' AS WeekNumberName
            ) AS CAL
        LEFT OUTER JOIN MyTable MT ON
            MT.Week = CAL.WeekNumber
    ) AS SourceTable
    PIVOT
    (
        MAX(Mark)
        FOR WeekNumberName IN ([Week 1], [Week 2], [Week 3], [Week 4], [Week 5])
    ) AS PivotTable

您可以通过一个日历表来实现这一点。在我的大多数数据库中,我通常都有一个物理表,其中可以包含周数(特别是因为一些企业可能会以稍微不同的方式处理这些周数-是星期三,1月1日第1周还是前一年第52周?),业务季度,假期,或者特定企业可能需要的任何其他内容

您还可以使用虚拟表执行此操作,如图所示。当然,您需要将周数扩展到52周

SELECT
    PersonID, [Week 1], [Week 2], [Week 3], [Week 4], [Week 5]
FROM
    (
        SELECT
            MT.PersonID, MT.Mark, CAL.WeekNumberName
        FROM
            (
                SELECT 1 AS WeekNumber, 'Week 1' AS WeekNumberName
                UNION ALL
                SELECT 2 AS WeekNumber, 'Week 2' AS WeekNumberName
                UNION ALL
                SELECT 3 AS WeekNumber, 'Week 3' AS WeekNumberName
                UNION ALL
                SELECT 4 AS WeekNumber, 'Week 4' AS WeekNumberName
                UNION ALL
                SELECT 5 AS WeekNumber, 'Week 5' AS WeekNumberName
            ) AS CAL
        LEFT OUTER JOIN MyTable MT ON
            MT.Week = CAL.WeekNumber
    ) AS SourceTable
    PIVOT
    (
        MAX(Mark)
        FOR WeekNumberName IN ([Week 1], [Week 2], [Week 3], [Week 4], [Week 5])
    ) AS PivotTable

如果您想在
myTable
中由于pivot查询中的左连接而缺少一周的时间时摆脱第一个讨厌的空行,那么可以在末尾添加where语句。。另外,你真的不需要把所有的工会都打出来

WITH WeeksCTE AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY t.WeekNum) WeekNum 
    FROM (VALUES(1), (2), (3), (4), (5), (6), (7), (8)) t(WeekNum), 
         (VALUES(1), (2), (3), (4), (5), (6), (7), (8)) c(WeekNum)
)
SELECT  *
FROM (
    SELECT  CONCAT('Week ', WeekNum) WeekName,
            mt.PersonId,
            mt.Mark
    FROM    WeeksCTE cte
            LEFT JOIN mytable mt ON cte.WeekNum = mt.[Week]
) t
PIVOT
(
    MAX(Mark)
    FOR WeekName IN (
        [Week 1],[Week 2],[Week 3],[Week 4],[Week 5],[Week 6],[Week 7],[Week 8],[Week 9],[Week 10],
        [Week 11],[Week 12],[Week 13],[Week 14],[Week 15],[Week 16],[Week 17],[Week 18],[Week 19],[Week 20],
        [Week 21],[Week 22],[Week 23],[Week 24],[Week 25],[Week 26],[Week 27],[Week 28],[Week 29],[Week 30],
        [Week 31],[Week 32],[Week 33],[Week 34],[Week 35],[Week 36],[Week 37],[Week 38],[Week 39],[Week 40],
        [Week 41],[Week 42],[Week 43],[Week 44],[Week 45],[Week 46],[Week 47],[Week 48],[Week 49],[Week 50],
        [Week 51],[Week 52]
    )
) p
WHERE PersonID IS NOT NULL

如果你想摆脱第一个讨厌的空行,当你在
myTable
中由于pivot查询中的左连接而缺少一周时,你可以在末尾添加一个where语句。。另外,你真的不需要把所有的工会都打出来

WITH WeeksCTE AS 
(
    SELECT ROW_NUMBER() OVER(ORDER BY t.WeekNum) WeekNum 
    FROM (VALUES(1), (2), (3), (4), (5), (6), (7), (8)) t(WeekNum), 
         (VALUES(1), (2), (3), (4), (5), (6), (7), (8)) c(WeekNum)
)
SELECT  *
FROM (
    SELECT  CONCAT('Week ', WeekNum) WeekName,
            mt.PersonId,
            mt.Mark
    FROM    WeeksCTE cte
            LEFT JOIN mytable mt ON cte.WeekNum = mt.[Week]
) t
PIVOT
(
    MAX(Mark)
    FOR WeekName IN (
        [Week 1],[Week 2],[Week 3],[Week 4],[Week 5],[Week 6],[Week 7],[Week 8],[Week 9],[Week 10],
        [Week 11],[Week 12],[Week 13],[Week 14],[Week 15],[Week 16],[Week 17],[Week 18],[Week 19],[Week 20],
        [Week 21],[Week 22],[Week 23],[Week 24],[Week 25],[Week 26],[Week 27],[Week 28],[Week 29],[Week 30],
        [Week 31],[Week 32],[Week 33],[Week 34],[Week 35],[Week 36],[Week 37],[Week 38],[Week 39],[Week 40],
        [Week 41],[Week 42],[Week 43],[Week 44],[Week 45],[Week 46],[Week 47],[Week 48],[Week 49],[Week 50],
        [Week 51],[Week 52]
    )
) p
WHERE PersonID IS NOT NULL

你能把DDL和DML语句放在粘贴箱或其他地方吗?sqlfiddle是死的。DDL和DML(最好是仍能证明问题的最小数量)应该是问题的一部分,而不是在任何外部站点上,因此,问题和答案都完全包含在这里。请参阅更新的问题应该是编写52个
CASE
表达式的简单事项。您可以将DDL和DML语句放在粘贴箱或其他地方吗?SQLFIDLE是DDL和DML的死区(最好是仍然显示问题的最小数量)应该是问题的一部分,而不是在任何外部网站上,因此问题和答案都完全包含在这里。请参阅更新的问题,只需编写52个
CASE
表达式即可。下面的选择可以直接生成52个数字。我认为这样可以消除所有部分或单独日历表的联合。这是针对oracle数据库的,但我认为您可以理解。“按级别选择级别1 week_与dual connect的偏移量问题是针对SQL Server的,我相信dual是一个Oracle特定的构造。工会只是为了演示一般的想法,即一个人需要有一个开始的周的结果集,然后将其外部联接。下面的选择可以生成52个数字di直截了当。我认为这样可以消除UNION all部分或单独的日历表。这是针对oracle数据库的,但我认为您可以理解这一点。“选择级别1周\u从dual connect中逐级偏移问题是针对SQL Server的,我相信dual是oracle特定的构造。工会只是在那里展示一个总的想法,那就是一个人需要有一个星期的结果集开始,然后离开外部加入到这一点。