【问题标题】:Find out whether no records have been created in the last x number of days查看过去 x 天是否没有创建记录
【发布时间】:2011-09-09 17:02:12
【问题描述】:

假设我有一个数据库来跟踪结构如下所示的浇水植物:

Table: "Plants"
ID     Plants
----------------------------------
1      Roses
2      Daisies
3      Sunflowers
4      Marigolds
5      Daffodils

Table: "Maintenance"
ID    Plant_ID    Activity    Date
-------------------------------------
1     1            Water      2011-09-09
2     1            Water      2011-08-02
3     2            Water      2011-08-15
4     3            Water      2010-07-01
5     4            Weed       2010-07-01

我正在尝试编写一个查询来告诉我们植物是否需要浇水,如果需要,浇水程度如何。换句话说:如果植物在过去 30 天内没有浇水,则返回“黄色”警告级别;如果在过去 60 天内没有浇水,则警告级别为“红色”。

这是我目前所处的位置:

SELECT Plants.Plants, 
IF ( DATEDIFF(CURRENT_DATE, MAX(Maintenance.Date)) < 30 AND maintenance.type = "Water", '',
  IF ((DATEDIFF(CURRENT_DATE, MAX(Maintenance.Date)) >= 60 AND maintenance.type = "Water") or maintenance.date IS NULL, 'Red', 'Yellow')
) AS `Water Warning`,
IF ( DATEDIFF(CURRENT_DATE, MAX(Maintenance.Date)) < 30 and maintenance.type = "Weed" , '',
  IF ((DATEDIFF(CURRENT_DATE, MAX(Maintenance.Date)) >= 60 and maintenance.type = "Weed") or maintenance.date IS NULL, 'Red', 'Yellow')
) AS `Weeding Warning`
FROM `plants`
LEFT JOIN `maintenance` ON `maintenance`.`plant_id` = `plants`.`id`
GROUP BY `plants`.`id`;

但这会为“Roses”返回“红色”警告,而不是预期的空字符串,并且没有 Maintenance.Activity 的条件。请注意,同样的查询也需要对除草和其他活动执行类似的功能,因此在 WHERE 子句中进行过滤可能不是答案。

这是我想要的:

Results
ID     Plants        "Water Warning"  "Weed Warning"
----------------------------------------------------
1      Roses               ""             "Red"
2      Daisies           "Yellow"         "Red"
3      Sunflowers         "Red"           "Red"
4      Marigolds          "Red"            ""
5      Daffodils          "Red"           "Red"

【问题讨论】:

  • "为了清楚起见,我将我正在处理的实际查询过分简化了,所以如果我在此处输入的内容中存在标点符号或其他问题,那不是导致问题的原因。”然后使用简化的测试用例重新运行您的测试,这样我们就知道在我们开始为您处理之前没有一些微不足道的复制错误。就这个问题而言,这些是您真正的疑问
  • 我已根据您的建议编辑了问题。我希望现在不要太复杂。

标签: mysql if-statement max intervals


【解决方案1】:

使用下面的语句,您只需将表格与植物名称连接起来。

SELECT *, 

CASE
    WHEN DATEDIFF(CURRENT_DATE, DATE) >= 60 THEN 'RED'
    WHEN DATEDIFF(CURRENT_DATE, DATE) >= 30 THEN 'YELLOW'
END AS FLAG
FROM test_table

【讨论】:

  • 很抱歉作为另一个回答者,但您的回答与 OP 没有区别。
【解决方案2】:

我真的希望有一个更优雅的解决方案,但这有效:

SELECT 
`plants`.`plants`,
IF((MAX(IF(`maintenance`.`type` = 'Water',
        `maintenance`.`date`,
        NULL)) IS NULL) OR ((DATEDIFF(CURRENT_DATE,
            MAX(IF(`maintenance`.`type` = 'Water',
                `maintenance`.`date`,
                NULL)))) > 30),
    (IF((MAX(IF(`maintenance`.`type` = 'Water',
            `maintenance`.`date`,
            NULL)) IS NULL) OR ((DATEDIFF(CURRENT_DATE,
                MAX(IF(`maintenance`.`type` = 'Water',
                    `maintenance`.`date`,
                    NULL)))) > 90),
        'red',
        'yellow')),
    '') AS `Water Warning`,
IF((MAX(IF(`maintenance`.`type` = 'Weed',
        `maintenance`.`date`,
        NULL)) IS NULL) OR ((DATEDIFF(CURRENT_DATE,
            MAX(IF(`maintenance`.`type` = 'Weed',
                `maintenance`.`date`,
                NULL)))) > 30),
    (IF((MAX(IF(`maintenance`.`type` = 'Weed',
            `maintenance`.`date`,
            NULL)) IS NULL) OR ((DATEDIFF(CURRENT_DATE,
                MAX(IF(`maintenance`.`type` = 'Weed',
                    `maintenance`.`date`,
                    NULL)))) > 90),
        'red',
        'yellow')),
    '') AS `Weed Warning`
FROM
`plants`
    LEFT JOIN
`maintenance` ON `maintenance`.`plant_id` = `plants`.`id`
GROUP BY `plants`.`id`;

【讨论】:

    【解决方案3】:

    实际数据

    mysql> 从植物中选择 *; +--------+------------+ |身份证 |植物 | +--------+------------+ | 1 |玫瑰 | | 2 |雏菊 | | 3 |向日葵 | | 4 |金盏花 | | 5 |水仙 | +--------+------------+ mysql> 从维护中选择 *; +----+------------+----------+------------+ |身份证 |植物_ID |活动 |日期 | +----+------------+----------+------------+ | 1 | 1 |水 | 2011-09-09 | | 2 | 1 |水 | 2011-08-02 | | 3 | 2 |水 | 2011-08-15 | | 4 | 3 |水 | 2010-07-01 | | 5 | 4 |杂草 | 2010-07-01 | +----+------------+----------+------------+
    SELECT
    Plants.Plants,
    COALESCE(
    CASE mt.Activity='Weed'
      WHEN 1 THEN
        CASE DATEDIFF(CURRENT_DATE, mt.last_date) BETWEEN 0 AND 30
          WHEN 1 THEN ''
          ELSE
            CASE DATEDIFF(CURRENT_DATE, mt.last_date) BETWEEN 30 AND 60
            WHEN 1 THEN 'Yellow'
            ELSE NULL
            END
        END
    END, 'Red') AS "Weed Warning",
    COALESCE(
    CASE mt.Activity='Water'
      WHEN 1 THEN
        CASE DATEDIFF(CURRENT_DATE, mt.last_date) BETWEEN 0 AND 30
          WHEN 1 THEN ''
          ELSE
            CASE DATEDIFF(CURRENT_DATE, mt.last_date) BETWEEN 30 AND 60
            WHEN 1 THEN 'Yellow'
            ELSE NULL
            END
        END
    END, 'Red') AS "Water Warning"
    FROM Plants
    LEFT JOIN
    ( SELECT Plant_ID, Activity, MAX(Date) AS last_date
      FROM Maintenance
      GROUP BY Plant_ID, Activity) AS mt ON Plants.ID=mt.Plant_ID
    GROUP BY Plants.ID;
    

    结果

    +------------+--------------+----------------+ |植物 |杂草警告 |水警告 | +------------+--------------+----------------+ |玫瑰 |红色 | | |雏菊 |红色 | | |向日葵 |红色 |红色 | |金盏花 |红色 |红色 | |水仙 |红色 |红色 | +------------+--------------+----------------+

    OP 说明

    1. 您发布了错误的结果
    2. 您已参考不存在列type
    3. 您没有注意表名是否区分大小写

    【讨论】:

    • 您的回答很有趣,但在我的最终查询中,实际日期将是最终用户定义的变量。据我了解,我认为这种方法当时行不通。抱歉,我在原帖中没有说清楚。
    • 你试过了吗?你是什​​么意思用户提供实际日期? (我看不出有什么区别)
    • “红色”和“黄色”间隔将是不同的数字。所以可能 20 天是黄色警告,100 天是红色警告。
    • 我对这个问题进行了相当多的编辑。我希望你能留下来试着回答它。你清楚地知道你的东西!
    • 这不起作用。 :( 如果我在 Roses 上添加一条日期为昨天的“杂草”记录,它仍然会出现红色警告。