【问题标题】:Joining table of different conditions不同条件的连接表
【发布时间】:2021-09-04 08:11:58
【问题描述】:

我希望在不同的条件下加入一个表两次。即使上面的行没有意义,也请阅读下面的示例。我尝试使用 CASE WHEN 左加入同一个表,但没有得到所需的输出,而且我是 SQL 新手。

有一个名为MeterReading 的表,其中包含特定月份的抄表值。我想创建一个连接表,其中包含当月的抄表,以及上个月的抄表值。

月份和年份是整数值。示例中的所有内容都是整数值。

读表

MeterID YearVal MonthVal ReadingVal UsingVal
1 2020 1 100 150
2 2020 2 120 140
3 2020 3 180 200
...
12 2020 12 140 200
13 2021 1 230 170
14 2021 2 120 100

我正在寻找的输出是这样的:

MeterID YearVal MonthVal ReadingVal UsingVal PrevVal PrevUsingVal
1 2020 1 100 150 NULL NULL
2 2020 2 120 140 100 150
3 2020 3 180 200 120 140
...
12 2020 12 140 200 ... ...
13 2021 1 230 170 140 200
14 2021 2 120 100 230 170

还要注意,由于年月是整数,所以 2021 01 的前一个是 2020 12。

我尝试的查询是(再次,我对 SQL 很陌生):

SELECT
MR.meterid ,
MR.year_val,
MR.month_val,
MR.reading_val,
MR.using_val,
TMR.Meterid,
TMR.YV2,
TMR.MV2,
TMR.RV1,
TMR.UV2,
0 AS DelFlag
From MeterReading MR
LEFT JOIN
(
    SELECT
    MR.meterid,
    MR.Reading_val AS RV1 ,
    MR.using_val AS UV2,
    CASE WHEN MR.Month_val = 1 THEN 12 ELSE MR.Month_val - 1  END AS MV2,
    CASE WHEN MR.month_val = 1 THEN MR.year_val + 1 ELSE MR.year_val END AS YV2
    FROM MeterReading MR
) TMR
ON
MR.meterid = TMR.meterid AND
MR.year_val = TMR.YV2 AND
MR.month_val = TMR.MV2

我没有得到预期的结果。请用简单的解释指导我。

【问题讨论】:

  • 查看lag窗口函数。
  • 谢谢斯图。这很有帮助..但是如果有不规则的条目怎么办...有没有办法..谢谢

标签: mysql sql database join rdbms


【解决方案1】:

如果你有每个月的数据,你可以使用一个简单的滞后:

select mr.*,
       lag(readingval) over (order by yearval, monthval) as prev_readingval,
       lag(usingval) over (order by yearval, monthval) as prev_usingval
from MeterReading mr;

如果您可能缺少数据并且您想将其视为NULL(而不是转到数据中的上个月),您仍然可以使用窗口函数,但使用range 窗口框架:

select mr.*,
       sum(readingval) over (order by yearval * 12 + monthval
                             range between 1 preceding and 1 preceding
                            ) as prev_readingval,
       lag(usingval) over (order by yearval * 12 + monthval
                           range between 1 preceding and 1 preceding
                          ) as prev_usingval
from MeterReading mr;

【讨论】:

    【解决方案2】:

    LAG() 应该适用于简单的情况。但是,如果您想要更大的灵活性,应该首选使用JOIN。您可以尝试以下方法:

    SELECT          currentYear.MeterID, currentYear.YearVal, currentYear.MonthVal, currentYear.ReadingVal, currentYear.UsingVal, previousYear.ReadingVal AS PrevVal, previousYear.UsingVal AS PrevUsingVal
    FROM            #MeterReading currentYear
    LEFT JOIN       #MeterReading previousYear ON (currentYear.YearVal = previousYear.YearVal AND (currentYear.MonthVal - 1) = previousYear.MonthVal)
    WHERE           currentYear.MonthVal != 1
    UNION
    SELECT          currentYear.MeterID, currentYear.YearVal, currentYear.MonthVal, currentYear.ReadingVal, currentYear.UsingVal, previousYear.ReadingVal AS PrevVal, previousYear.UsingVal AS PrevUsingVal
    FROM            #MeterReading currentYear
    LEFT JOIN       #MeterReading previousYear ON ((currentYear.YearVal - 1) = previousYear.YearVal) AND (previousYear.MonthVal = 12)
    WHERE           currentYear.MonthVal = 1
    
    ORDER BY        currentYear.YearVal ASC, currentYear.MonthVal ASC
    

    【讨论】:

      【解决方案3】:

      我以非常初学者的方式做到了这一点,通过在 [ CASE WHEN ] 条件下使用 [ CASE WHEN ] 的条件加入同一张表,用于月份和年份的边界情况(即 2020 年 1 月的先前 val 应该获取 2019 年 12 月的值),

      查询:

      SELECT
        TMR.MeterID
      , TMR.YearVal
      , TMR.MonthVal
      , TMR.ReadingVal AS ReadingVal
      , TMR.UsingVal AS UsingVal
      , TMR2.ReadingVal AS PrevReadVal
      , TMR2.Using AS PrevUsingVal
      FROM MeterReading TMR
      LEFT JOIN 
      (
        SELECT
          TMR.MeterID
        , TMR.ReadingVal
        , TMR.UsingVal
        , CASE WHEN TMR.MonthVal = '12' THEN 1 ELSE TMR.MonthVal + 1 END AS MonthVal2
        , CASE WHEN TMR.MonthVal = '12' THEN TMR.YearVal + 1 ELSE TMR.YearVal END AS YearVal2
        FROM MeterReading TMR
      ) TMR2 ON
      TMR.MeterID = TMR2.MeterID
      AND TMR.YearVal = TMR2.YearVal2
      AND TMR.MonthVal = TMR2.MonthVal2
      

      【讨论】:

        猜你喜欢
        • 2014-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-01
        • 1970-01-01
        相关资源
        最近更新 更多