SQL Group 和 Pivot 将一对行合并为一行
Posted
技术标签:
【中文标题】SQL Group 和 Pivot 将一对行合并为一行【英文标题】:SQL Group and Pivot on pair of rows into one row 【发布时间】:2021-12-25 00:37:45 【问题描述】:我在 SQL Server 2016 表中有传感器数据,如下所示:
Created | RealValue | Tag | Units | PairIdentity | PairConfigLabel |
---|---|---|---|---|---|
2021-11-12 12:00:50.030 | 67.3519982 | temperature | °F | BC72251E-08C0-471A-93A3-C2422C7AB80C | Cutting |
2021-11-12 12:00:50.030 | 53.299999 | humidity | % | BC72251E-08C0-471A-93A3-C2422C7AB80C | Cutting |
2021-11-12 12:00:50.030 | 53.25 | humidity | % | 7D7F8DAC-5BCB-4077-961F-2A985BB6D8CE | Assembly |
2021-11-12 12:00:50.030 | 67.0279982 | temperature | °F | 7D7F8DAC-5BCB-4077-961F-2A985BB6D8CE | Assembly |
2021-11-12 12:00:50.013 | 36.849998 | humidity | % | 1A857346-35D2-45FA-80C8-D6523B310026 | Laminating |
2021-11-12 12:00:50.013 | 71.564 | temperature | °F | 1A857346-35D2-45FA-80C8-D6523B310026 | Laminating |
2021-11-12 12:00:49.997 | 42.700001 | humidity | % | E8FC1476-F082-4C79-889A-5716FCE0A5B8 | SLA Lab |
2021-11-12 12:00:49.997 | 72.482 | temperature | °F | E8FC1476-F082-4C79-889A-5716FCE0A5B8 | SLA Lab |
2021-11-12 12:00:49.980 | 41.049999 | humidity | % | D5C651A4-3A4C-429B-88CA-22CBFEDE875D | QC Lab |
2021-11-12 12:00:49.980 | 73.3459982 | temperature | °F | D5C651A4-3A4C-429B-88CA-22CBFEDE875D | QC Lab |
对于每个温度记录,通常,但不总是有一个相应的湿度读数(可能有湿度行,但没有相应的温度,反之亦然)。它们与PairIdentity
列绑定在一起。我想生成一个查询,该查询将 PairIdentity 上的数据分组并将其透视到一行中,每个分组都包含新列。我不确定我的措辞是否正确,但我正在努力达到与此类似的结果:
Created | Temp | TempUnit | Humidity | HumidityUnit | PairIdentity | PairConfigLabel |
---|---|---|---|---|---|---|
2021-11-12 12:00:50.030 | 67.3519982 | °F | 53.299999 | % | BC72251E-08C0-471A-93A3-C2422C7AB80C | Cutting |
2021-11-12 12:00:50.030 | 67.0279982 | °F | 53.25 | % | 7D7F8DAC-5BCB-4077-961F-2A985BB6D8CE | Assembly |
2021-11-12 12:00:50.013 | 71.564 | °F | 36.849998 | % | 1A857346-35D2-45FA-80C8-D6523B310026 | Laminating |
任何提示或帮助将不胜感激。
【问题讨论】:
对于同一个 F-% 讲座,PairIdentity 是唯一的吗? 【参考方案1】:这只是一个标准的case
pivot:
select
min(Created) as Created,
min(case when tag = 'temperature' then RealValue end) as Temp,
min(case when tag = 'temperature' then Units end) as TempUnit,
min(case when tag = 'humidity' then RealValue end) as Humidity,
min(case when tag = 'humidity' then Units end) as HumidityUnit,
PairIdentity,
min(PairConfigLabel) as PairConfigLabel
from T
group by PairIdentity
【讨论】:
这是该场景的最佳解决方案【参考方案2】:从您的示例数据看来,您只需要两个数据集之间的内部连接:
with tmp as (
select *
from t
where tag='temperature'
), hum as (
select *
from t
where tag='humidity'
)
select
t.Created Created,
t.RealValue Temp,
t.Units TempUnit,
h.RealValue HunidityUnit,
t.PairIdentity,
t.PairConfigLabel
from tmp t join hum h on t.PairIdentity=h.PairIdentity;
【讨论】:
这很好,但使用 SELECT * 不是好习惯 @Leandro 我不同意。在这里使用*
没有任何缺点。
在这样的独立 CTE 中,它不会返回最终结果集,这绝对没问题!
@Leandro 性能影响通常是当您将所有列返回给客户端时。这些当然不会被退回。考虑一下:select ... from (select * from T) Tderived
,这基本上就是您每次在 from 子句中提到表时所做的事情。
非常感谢!!!【参考方案3】:
我不知道我是否非常了解您的数据或结构,或者您想要什么,请在此处发表评论,我很乐意更新或更正我的答案。
主要想法是获得“两张桌子”,一张用于温度,另一张用于湿度,并通过您的PairIdentity
加入它们(如果在两种方法之间是唯一的)。
然后根据联接表的需要显示特定数据。
您可以使用“此连接”和真实数据来获得更高的精度。
SELECT
temp.Created,
temp.temperature as Temp,
temp.Units as TempUnit,
hum.humidity as Humidity,
hum.Units as HumidityUnit,
temp.PairIdentity,
temp.PairConfigLabel
FROM
(
SELECT
Created,
RealValue as temperature,
Units,
PairIdentity,
PairConfigLabel
FROM yourTable
WHERE Tag = 'temperature'
) as temp
JOIN
(
SELECT
Created,
RealValue as humidity,
Units,
PairIdentity,
PairConfigLabel
FROM yourTable
WHERE Tag = 'humidity'
) as hum
ON temp.PairIdentity = hum.PairIdentity
【讨论】:
谢谢!缺少括号(在 JOIN 之后)和“已创建”的列名不明确的语法错误,但它有效!不让我编辑以更正语法。 对不起,杰森,我是在飞行中完成的。让我修复它并感谢您的更新 @JasonEades 完成,再次感谢并再次为错误道歉。如果这对您有帮助并回答您,请不要忘记投票和/或将其标记为答案。或者请告诉我是否可以为您提供更多帮助或编辑我的答案。以上是关于SQL Group 和 Pivot 将一对行合并为一行的主要内容,如果未能解决你的问题,请参考以下文章
具有 group by 和/或 distinct 和 pivot 的复杂 SQL Server 查询
SQL Server - Pivot 将行转换为列(带有额外的行数据)