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 将一对行合并为一行的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server Pivot 隐藏group

具有 group by 和/或 distinct 和 pivot 的复杂 SQL Server 查询

SQL Server - Pivot 将行转换为列(带有额外的行数据)

带有条件的 Oracle SQL Pivot 将行转换为列

Oracle SQL group by 查询,一种 PIVOT [重复]

在 SQL 中使用“Pivot”将行转换为列