【问题标题】:MS SQL how to have values from two row in one?MS SQL如何将两行的值合二为一?
【发布时间】:2021-05-22 07:16:00
【问题描述】:

如何将两行的值合二为一? 就像我有以下原始数据

我想将其转换为:

这甚至可以用 MS SQL 实现吗?

这些是 Excel 表格,但我在 SQL Server 上有真实数据

说明: 对于每个 product_group_id 我想有 discount_id 的变化,而 discount_id 应该有 from_discount_id 和 to_discount_id ,

对于每个 product_group_id,最少有两个行,对于 product_group_id 的最后一个条目,新表中应该没有条目,因为现在发生了变化。

【问题讨论】:

  • 使用MINMAX?
  • 我不明白你是如何得到数据的。每组 N 行似乎在输出中变为 N-1 行。
  • min 和 max 无济于事,因为我可以进行 5 次更改 min max 应该如何帮助? @Larnu
  • @TimBiegeleisen 至于第N个没有变化,之后就没有更多的条目了
  • 如果该组数据的原始数据集中只有一行怎么办?

标签: sql sql-server sql-server-2012


【解决方案1】:

这可以使用窗口函数来完成:

SELECT *
FROM
    (
    SELECT
        h.PRODUCT_GROUP_ID,
        h.PID,
        LEAD(h.CHANGE_FROM) OVER (PARTITION BY h.PRODUCT_GROUP_ID 
                                   ORDER BY h.CHANGE_FROM ASC) AS CHANGE_FROM,
        h.PID as FROM_PID,
        h.DISCOUNT_ID as FROM_DISCOUNT_ID,
        LEAD(h.PID) OVER (PARTITION BY h.PRODUCT_GROUP_ID 
                          ORDER BY h.CHANGE_FROM ASC) as TO_PID,
        LEAD(h.DISCOUNT_ID) OVER (PARTITION BY h.PRODUCT_GROUP_ID
                                  ORDER BY h.CHANGE_FROM ASC) TO_DISCOUNT_ID,
        ROW_NUMBER() OVER (PARTITION BY h.PRODUCT_GROUP_ID 
                           ORDER BY h.CHANGE_FROM DESC) RowNoDesc
    FROM
        ProductGroupDiscountHistory h
    ) WithNext
WHERE
    WithNext.RowNoDesc <> 1
ORDER BY
    WithNext.PRODUCT_GROUP_ID,
    WithNext.CHANGE_FROM 

【讨论】:

  • 非常感谢,我会尝试并告诉我是否对我有用:D
  • 抱歉,我注意到我从错误的行中提取了“更改来源”。我现在已经更新,所以它是正确的。
  • 这对您来说效果如何?如果它成功了,请接受并支持答案。如果没有,请告诉我剩下的问题是什么,我会尽力解决。
【解决方案2】:

这是一个如何使用领先功能实现它的示例

with qq as (select id, 
                   change_from, 
                   discount_id from_discount_id, 
                   lead(discount_id) over(partition by id order by change_from) to_discount_id
           from test_t)

select * 
  from qq
 where to_discount_id is not null
 order by id

【讨论】:

    【解决方案3】:

    如果您愿意,也可以不使用LEADLAG 来执行此操作。以下语句使用INNER JOIN 条件,该条件连接两行 if

    • 他们的PRODUCT_GROUP_ID 是一样的,
    • 任一一行的CHANGE_TO日期比下一行的CHANGE_FROM日期早1天
    • 一行的PID比下一行的少1,更改日期分别为minmax为他们的PID

    这是我从上面的数据中得到的模式。

    一共

        SELECT   one.PRODUCT_GROUP_ID
               , one.PID
               , two.CHANGE_FROM
               , one.PID as FROM_PID
               , one.DISCOUNT_ID as FROM_DISCOUNT_ID
               , two.PID as TO_PID
               , two.DISCOUNT_ID as TO_DISCOUNT_ID
          FROM tab one
    INNER JOIN tab two
            ON one.PRODUCT_GROUP_ID = two.product_GROUP_ID
               AND (DATEADD(DAY, 1, one.CHANGE_TO) = two.CHANGE_FROM
                    OR one.PID = two.PID - 1
                       AND one.CHANGE_FROM IN (SELECT MAX(CHANGE_FROM) FROM tab WHERE PRODUCT_GROUP_ID = one.PRODUCT_GROUP_ID AND PID = one.PID)
                       AND two.CHANGE_FROM IN (SELECT MIN(CHANGE_FROM) FROM tab WHERE PRODUCT_GROUP_ID = one.PRODUCT_GROUP_ID AND PID = two.PID)
                    )
          ORDER BY one.PRODUCT_GROUP_ID, one.PID, two.CHANGE_FROM
    ;  
    

    产生你想要的结果。

    您可以在this db<>fiddle 进行测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-25
      • 2016-11-28
      • 2022-12-18
      • 2018-04-14
      • 1970-01-01
      相关资源
      最近更新 更多