将不重叠数据的多行合并为一行 SQL 服务器
Merge multiple rows without overlapping data into one row SQL Server
我有一个数据 table,数据如下:
ID
Task
time
Jim
sleep
5:50
Jim
wakeup
7:15
Bob
sleep
6:00
Bob
brushteeth
8:00
Bob
eat
9:00
我是运行一个生成以下内容的查询
SELECT
dbo.Person.ID,
CAST(CASE WHEN dbo.DailyActivities.Activity = 'sleep' THEN 1 ELSE 0 END AS bit) AS slept,
CAST(CASE WHEN dbo.DailyActivities.Activity = 'wakeup' THEN 1 ELSE 0 END AS bit) AS wokeup,
CAST(CASE WHEN dbo.DailyActivities.Activity = 'brushteeth' THEN 1 ELSE 0 END AS bit) AS brushedteeth,
CAST(CASE WHEN dbo.DailyActivities.Activity = 'eat' THEN 1 ELSE 0 END AS bit) AS ate
FROM
dbo.Person
LEFT OUTER JOIN
dbo.DailyActivities ON dbo.Person.ID = dbo.DailyActivities.ID
ID
slept
wokeup
brushedteeth
ate
Jim
TRUE
FALSE
FALSE
FALSE
Jim
FALSE
TRUE
FALSE
FALSE
Bob
TRUE
FALSE
FALSE
FALSE
Bob
FALSE
FALSE
TRUE
FALSE
Bob
FALSE
FALSE
FALSE
TRUE
我们如何获得如下所示每行 1 个 ID 的结果
ID
slept
wokeup
brushedteeth
ate
Jim
TRUE
TRUE
FALSE
FALSE
Bob
TRUE
FALSE
TRUE
TRUE
最简单的方法是使用 DISTINCT + 子查询 + CASE。我稍微简化了您的查询,所以没有加入等,所以我必须少输入一些。但我希望它背后的概念是清楚的。
SELECT DISTINCT
p.[ID]
, CASE
WHEN (SELECT COUNT(*) FROM [dbo].[Person] sub WHERE sub.[ID] = p.[ID] AND sub.[Task] = 'slept') > 0 THEN CAST(1 as bit)
ELSE CAST(0 as bit)
END AS [slept]
, CASE
WHEN (SELECT COUNT(*) FROM [dbo].[Person] sub WHERE sub.[ID] = p.[ID] AND sub.[Task] = 'wakeup') > 0 THEN CAST(1 as bit)
ELSE CAST(0 as bit)
END AS [wokeup]
, CASE
WHEN (SELECT COUNT(*) FROM [dbo].[Person] sub WHERE sub.[ID] = p.[ID] AND sub.[Task] = 'brushteeth') > 0 THEN CAST(1 as bit)
ELSE CAST(0 as bit)
END AS [brushteeth]
, CASE
WHEN (SELECT COUNT(*) FROM [dbo].[Person] sub WHERE sub.[ID] = p.[ID] AND sub.[Task] = 'eat') > 0 THEN CAST(1 as bit)
ELSE CAST(0 as bit)
END AS [ate]
FROM [dbo].[Person] p
正如我在评论中提到的,在 CASE
表达式周围使用 MAX
;这称为条件聚合:
SELECT P.ID,
CAST(MAX(CASE WHEN DA.Activity = 'sleep' THEN 1 ELSE 0 END) AS bit) AS slept,
CAST(MAX(CASE WHEN DA.Activity = 'wakeup' THEN 1 ELSE 0 END) AS bit) AS wokeup,
CAST(MAX(CASE WHEN DA.Activity = 'brushteeth' THEN 1 ELSE 0 END) AS bit) AS brushedteeth,
CAST(MAX(CASE WHEN DA.Activity = 'eat' THEN 1 ELSE 0 END) AS bit) AS ate
FROM dbo.Person P
LEFT OUTER JOIN dbo.DailyActivities DA ON P.ID = DA.ID
GROUP BY P.ID
此外,正如我在评论中提到的,我删除了列上的 3+ 部分命名,因为它 will be deprecated。
我有一个数据 table,数据如下:
ID | Task | time |
---|---|---|
Jim | sleep | 5:50 |
Jim | wakeup | 7:15 |
Bob | sleep | 6:00 |
Bob | brushteeth | 8:00 |
Bob | eat | 9:00 |
我是运行一个生成以下内容的查询
SELECT
dbo.Person.ID,
CAST(CASE WHEN dbo.DailyActivities.Activity = 'sleep' THEN 1 ELSE 0 END AS bit) AS slept,
CAST(CASE WHEN dbo.DailyActivities.Activity = 'wakeup' THEN 1 ELSE 0 END AS bit) AS wokeup,
CAST(CASE WHEN dbo.DailyActivities.Activity = 'brushteeth' THEN 1 ELSE 0 END AS bit) AS brushedteeth,
CAST(CASE WHEN dbo.DailyActivities.Activity = 'eat' THEN 1 ELSE 0 END AS bit) AS ate
FROM
dbo.Person
LEFT OUTER JOIN
dbo.DailyActivities ON dbo.Person.ID = dbo.DailyActivities.ID
ID | slept | wokeup | brushedteeth | ate |
---|---|---|---|---|
Jim | TRUE | FALSE | FALSE | FALSE |
Jim | FALSE | TRUE | FALSE | FALSE |
Bob | TRUE | FALSE | FALSE | FALSE |
Bob | FALSE | FALSE | TRUE | FALSE |
Bob | FALSE | FALSE | FALSE | TRUE |
我们如何获得如下所示每行 1 个 ID 的结果
ID | slept | wokeup | brushedteeth | ate |
---|---|---|---|---|
Jim | TRUE | TRUE | FALSE | FALSE |
Bob | TRUE | FALSE | TRUE | TRUE |
最简单的方法是使用 DISTINCT + 子查询 + CASE。我稍微简化了您的查询,所以没有加入等,所以我必须少输入一些。但我希望它背后的概念是清楚的。
SELECT DISTINCT
p.[ID]
, CASE
WHEN (SELECT COUNT(*) FROM [dbo].[Person] sub WHERE sub.[ID] = p.[ID] AND sub.[Task] = 'slept') > 0 THEN CAST(1 as bit)
ELSE CAST(0 as bit)
END AS [slept]
, CASE
WHEN (SELECT COUNT(*) FROM [dbo].[Person] sub WHERE sub.[ID] = p.[ID] AND sub.[Task] = 'wakeup') > 0 THEN CAST(1 as bit)
ELSE CAST(0 as bit)
END AS [wokeup]
, CASE
WHEN (SELECT COUNT(*) FROM [dbo].[Person] sub WHERE sub.[ID] = p.[ID] AND sub.[Task] = 'brushteeth') > 0 THEN CAST(1 as bit)
ELSE CAST(0 as bit)
END AS [brushteeth]
, CASE
WHEN (SELECT COUNT(*) FROM [dbo].[Person] sub WHERE sub.[ID] = p.[ID] AND sub.[Task] = 'eat') > 0 THEN CAST(1 as bit)
ELSE CAST(0 as bit)
END AS [ate]
FROM [dbo].[Person] p
正如我在评论中提到的,在 CASE
表达式周围使用 MAX
;这称为条件聚合:
SELECT P.ID,
CAST(MAX(CASE WHEN DA.Activity = 'sleep' THEN 1 ELSE 0 END) AS bit) AS slept,
CAST(MAX(CASE WHEN DA.Activity = 'wakeup' THEN 1 ELSE 0 END) AS bit) AS wokeup,
CAST(MAX(CASE WHEN DA.Activity = 'brushteeth' THEN 1 ELSE 0 END) AS bit) AS brushedteeth,
CAST(MAX(CASE WHEN DA.Activity = 'eat' THEN 1 ELSE 0 END) AS bit) AS ate
FROM dbo.Person P
LEFT OUTER JOIN dbo.DailyActivities DA ON P.ID = DA.ID
GROUP BY P.ID
此外,正如我在评论中提到的,我删除了列上的 3+ 部分命名,因为它 will be deprecated。