查询以查找最近的较短日期

时间:2018-06-19 10:36:10

标签: mysql sql case aggregate-functions

我有一张午餐生效日期和费率的表格。

我需要为每个effective date (created_on)列显示最接近的date小费率。

lunch_rate表:

created_on |   rate
-----------+-------
2018-06-01 |   30
2018-06-04 |   60

这是我试图做的事情:

    SELECT userId, 
    SUM(CASE WHEN date= '2018-06-01' AND lunchStatus = 1 THEN (SELECT MAX(rate) FROM lunch_rate WHERE DATE(created_on) <= date LIMIT 1) ELSE 0 END) '2018-06-01',
    SUM(CASE WHEN date= '2018-06-02' AND lunchStatus = 1 THEN (SELECT MAX(rate) FROM lunch_rate WHERE DATE(created_on) <= date LIMIT 1) ELSE 0 END) '2018-06-02',
    SUM(CASE WHEN date= '2018-06-03' AND lunchStatus = 1 THEN (SELECT MAX(rate) FROM lunch_rate WHERE DATE(created_on) <= date LIMIT 1) ELSE 0 END) '2018-06-03',
    SUM(CASE WHEN date= '2018-06-04' AND lunchStatus = 1 THEN (SELECT MAX(rate) FROM lunch_rate WHERE DATE(created_on) <= date LIMIT 1) ELSE 0 END) '2018-06-04'
    FROM
    (        
        SELECT userId, lunchStatus, DATE(issuedDateTime) as date 
        FROM `lunch_status` 
        WHERE DATE(issuedDateTime) BETWEEN '2018-06-01' AND '2018-06-04'        
    ) as a
    GROUP BY userId;

但是这个查询只给出了所有的最大费率,而没有考虑最近的生效日期。

结果如下:

userId    |   2018-06-01   |   2018-06-02  |  2018-06-03  |  2018-06-04
------------------------------------------------------------------------
131       |   60           |   60          |   0          |  60   
132       |   60           |   60          |  60          |   0
133       |   0            |    0          |   0          |  60
134       |   0            |    0          |   0          |  60

预期结果:

userId    |   2018-06-01   |   2018-06-02  |  2018-06-03  |  2018-06-04
------------------------------------------------------------------------
131       |   30           |   30          |   0          |  60   
132       |   30           |   30          |  30          |   0
133       |   0            |    0          |   0          |  60
134       |   0            |    0          |   0          |  60

SUM(CASE WHEN ... THEN (SELECT MAX(rate) FROM lunch_rate WHERE DATE(created_on) <= date LIMIT 1) ELSE 0 END) ....',

如何选择当日有效的午餐价格?

2 个答案:

答案 0 :(得分:1)

您可以尝试这样的事情:

SELECT lr1.rate
FROM   lunch_rate lr1
WHERE  lr1.created_on <= my_date
  AND  NOT EXISTS (SELECT *
                   FROM   lunch_rate lr2
                   WHERE  lr2.created_on > lr1.created_on
                     AND  lr2.created_on <= my_date);

答案 1 :(得分:1)

如果我理解正确,您需要在子查询中进行计算:

SELECT userId, 
       SUM(CASE WHEN date = '2018-06-01' AND lunchStatus = 1
                THEN rate ELSE 0
           END) as `2018-06-01`,
       SUM(CASE WHEN date = '2018-06-02' AND lunchStatus = 1
                THEN rate ELSE 0
           END) as `2018-06-02`,
       SUM(CASE WHEN date = '2018-06-03' AND lunchStatus = 1
                THEN rate ELSE 0
           END) as `2018-06-03`,
       SUM(CASE WHEN date = '2018-06-04' AND lunchStatus = 1
                THEN rate ELSE 0
           END) as `2018-06-04`
FROM (SELECT ls.*, DATE(ls.issuedDateTime) as date
             (SELECT lr.rate
              FROM lunch_rate lr
              WHERE DATE(lr.created_on) <= DATE(ls.issuedDateTime)
              ORDER BY lr.created_on DESC
              LIMIT 1
             ) as rate
      FROM lunch_status ls
      WHERE DATE(issuedDateTime) BETWEEN '2018-06-01' AND '2018-06-04'        
     ) lr
GROUP BY lr.userId;

请注意其他更改:

  • lunch_rate的子查询不使用MAX()。相反,它使用ORDER BY
  • 列别名由反引号包围,而不是单引号。我不赞同这些名字(因为它们需要被转义)。但是如果你想要它们,请使用正确的转义字符。
  • 表格给出合理的别名,列名称合格。