SQL Server 2008 R2 – 将多行减少为一行

Posted

技术标签:

【中文标题】SQL Server 2008 R2 – 将多行减少为一行【英文标题】:SQL Server 2008 R2 – Reducing multiple rows into one 【发布时间】:2015-01-15 14:40:44 【问题描述】:

我需要让我的数据在一行中显示个人在过去 3 年内是否有'完成'特定课程。

这是我的 existing 表和 desired 表(希望此链接有效,因为我还不能发布图片!): http://i.stack.imgur.com/c8oJO.png

我试过这段代码:

SELECT DISTINCT
EN,
(First_Name + ' ' + Last_Name) as Name,

First_Aid = CASE
WHEN Course = 'First Aid' 
and Status = 'Finished'
and Course_Start_Date > DATEADD(day, -1095, GETDATE())
THEN 'F'
ELSE 'Nope'
END,

Manual_Handling = CASE
WHEN Course = 'Manual Handling'
and Status = 'Finished'
and Course_Start_Date > DATEADD(day, -1095, GETDATE())
THEN 'F'
ELSE 'Nope'
END,

Fire_Safety = CASE
WHEN Course = 'Fire Safety'
and Status = 'Finished'
and Course_Start_Date > DATEADD(day, -1095, GETDATE())
THEN 'F'
ELSE 'Nope'
END
into MyTraining
FROM Learning_History`

这会产生准确的结果,但每个 CASE 语句都有一个单独的行(加上一个包含所有“否”结果的额外行)。所以我尝试了这段代码:

SELECT 
EN,
(First_Name + ' ' + Last_Name) as Name,

First_Aid =MAX(CASE
WHEN Course = 'First Aid' 
and Status = 'Finished'
and Course_Start_Date > DATEADD(day, -1095, GETDATE())
THEN 'F'
ELSE 'Nope'
END),

Manual_Handling =MAX(CASE
WHEN Course = 'Manual Handling' 
and Status = 'Finished'
and Course_Start_Date > DATEADD(day, -1095, GETDATE())
THEN 'F'
ELSE 'Nope'
END),

Fire_Safety =MAX(CASE
WHEN Course = 'Fire Safety' 
and Status = 'Finished'
and Course_Start_Date > DATEADD(day, -1095, GETDATE())
THEN 'F'
ELSE 'Nope'
END)

into MyTraining
FROM Learning_History

Group By EN,First_Name, Last_Name

此代码确实产生 1 行 - 但所有结果都是“不”。

我不太了解这方面的内容(只是在 Google 上搜索了大部分代码),因为我是 SQL 的初学者(所以我可能犯了一些简单的错误)。我认为数据透视表可能是要走的路 - 但我无法理解它们......

【问题讨论】:

【参考方案1】:

您可以像您正在尝试的那样使用 PIVOT 或 case 和 group by 来做到这一点。

PIVOT 示例:

select
    EN,
    [First Aid],
    [Manual Handling],
    [Fire Safety]
from (
    select
        [EN],
        [Course],
        [Status]
    from (
        select
            ROW_NUMBER() OVER (
                PARTITION BY
                    EN,Course
                ORDER BY
                    Course_Start_Date
            ) rID,
            *
        from (
            select
            *
            from (
                values
                    (1,'First Aid','1999-06-22','Finished'),
                    (1,'First Aid','2013-02-19','Finished'),
                    (1,'Manual Handling','2014-02-10','Cancelled'),
                    (1,'Manual Handling','2014-03-20','Finished'),
                    (1,'Fire Safety','2099-07-29','Finished'),
                    (1,'Fire Safety','2014-11-19','No Show')
            ) myTable ([EN],[Course],[Course_Start_Date],[Status])
        ) myTable
    )T
    where
        rID = 1
) S
PIVOT (
    MAX(Status) FOR Course IN ([First Aid],[Manual Handling],[Fire Safety])
) PVT

PS.: 我假设 EN 是 PRIMARY KEY

编辑:再试一次,)

【讨论】:

感谢 mxix。我不太了解这个,但我让它运行正常。不过,它似乎没有检查课程开始日期。此外 - 它返回 41000 行,而原始表中这 3 门课程只有 4000 行。谢谢你' 感谢 mxix。不能让这个为我工作。我不了解数据透视表,所以无法弄清楚发生了什么。不过感谢您的帮助。我现在发现,如果我去掉我的案例陈述中的“Else..”部分,它就会在一行中起作用。不是我想要的——但会坚持使用这段代码。

以上是关于SQL Server 2008 R2 – 将多行减少为一行的主要内容,如果未能解决你的问题,请参考以下文章

将 SQL Server 2008 r2 降级到 SQL Server 2008

如何将 SQL Server 2008 R2 SSIS 包升级到 SQL Server 2016?

windows 2012 r2怎么安装sql server 2008 r2

如何将所有数据库(快速)自 sql server 2008 express 传递到 sql server 2008 R2(无 express)

sql 2008 r2 在sql 2008上兼容么

windows server 2012 可以安装sql2008 吗