MySQL:如何选择最新日期在特定日期之前的记录

标签 mysql date select

假设一个简单的表如下,其中包含两个用户的状态事件。 status_id 为 1 使它们处于“事件”状态,其他任何值都使它们处于非事件状态。 我需要找出所有那些在一年内变得不活跃的用户,例如,2015-05-01(不包括该日期)。

CREATE TABLE user_status(
      user_id INT,
      status_id INT,
      date_assigned VARCHAR(10) );

 INSERT INTO user_status( user_id, status_id, date_assigned)
 VALUES
 (1234, 1, '2015-01-01'), -- 1234 becomes active (status id = 1)
 (1234, 2, '2015-07-01'), -- 1234 de-activated for reason 2

 (5678, 1, '2015-02-01'), -- 5678 becomes active (status id = 1)
 (5678, 3, '2015-04-01'), -- 5678 de-activated for reason 3
 (5678, 5, '2015-06-01'); -- 5678 de-activated for reason 5

使用查询

SELECT t1.*
FROM user_status t1
WHERE t1.date_assigned = (SELECT MIN(t2.date_assigned)       -- the first occurrence
                          FROM  user_status t2
                          WHERE t2.user_id =  t1.user_id     -- for this user
                          AND t2.status_id <> 1              -- where status not active
                          AND t2.date_assigned BETWEEN       -- within 1 yr of given date
                               '2015-05-01' + INTERVAL 1 DAY -- (not including that date)
                          AND 
                               '2015-05-01' + INTERVAL 1 YEAR 
                          )

我可以得到结果

user_id   status_id   date_assigned
 1234       2          2015-07-01
 5678       5          2015-06-01

这在某种程度上是正确的,但用户 5678 不应该在那里,因为尽管他们在日期范围内有一个不活跃的事件,但他们在所需的日期范围开始之前已经不活跃,因此没有成为不活跃在那个范围内。

我需要在我的查询中添加一点“仅向我显示那些有非事件事件的用户,其中该用户的先前 status_id 为 1,即他们在非事件事件发生的时间。

有谁能帮我把语法改正吗?
参见 SQL fiddle

最佳答案

您可以将 NOT EXISTS 添加到您的查询中:

SELECT t1.*
FROM user_status t1
WHERE t1.date_assigned = (SELECT MIN(t2.date_assigned)       -- the first occurance
                          FROM  user_status t2
                          WHERE t2.user_id =  t1.user_id     -- for this user
                          AND t2.status_id <> 1              -- where status not active
                          AND t2.date_assigned BETWEEN       -- within 1 yr of given date
                               '2015-05-01' + INTERVAL 1 DAY -- (not including that date)
                          AND 
                               '2015-05-01' + INTERVAL 1 YEAR 
                          )
      AND NOT EXISTS (SELECT 1                         -- such a record should not exist
                      FROM user_status t3
                      WHERE t3.user_id =  t1.user_id   -- for this user
                             AND t3.status_id <> 1     -- where status is not active
                             AND t3.date_assigned <    -- before the examined period
                               '2015-05-01' + INTERVAL 1 DAY )

Demo here

编辑:

您可以使用以下查询,该查询还考虑了具有多个激活日期的情况:

SELECT *
FROM user_status
WHERE (user_id, date_assigned) IN (
  -- get last de-activation date   
  SELECT t1.user_id, MAX(t1.date_assigned)
  FROM user_status AS t1
  JOIN (
    -- get last activation date 
    SELECT user_id, MAX(date_assigned) AS activation_date
    FROM user_status 
    WHERE status_id = 1
    GROUP BY user_id
  ) AS t2 ON t1.user_id = t2.user_id AND t1.date_assigned > t2.activation_date
  GROUP BY user_id
  HAVING MAX(date_assigned) BETWEEN '2015-05-01' + INTERVAL 1 DAY AND '2015-05-01' + INTERVAL 1 YEAR AND
         MIN(date_assigned) > '2015-05-01' + INTERVAL 1 DAY)

关于MySQL:如何选择最新日期在特定日期之前的记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36893234/

相关文章:

mysql - 以 "dd.mm.yyyy"等格式在表中插入日期

MySql 在同一查询中更新和选择

mysql - 如何缓存不经常更改的mysql查询?

php - 使用数组自动生成更新表单

php - MySQL函数拉父而不是当前行

javascript - 比较日期时间逻辑

java - 给定出生日期计算下一个生日日期?

jquery 获取 select() 选择

mysql - sql 告诉已经过去了多少天(datediff)

php - 使用 Ajax 和 PHP 访问 mySQL 字段