简体   繁体   English

MySQL:仅在最接近日期具有列值的地方选择行

[英]MySQL: select row only where closest to date has column value

I want to return all rows that were public in May (2019-05), so if a row was turned to draft (and not back to public) at any point before the end of May, I don't want it. 我想返回所有在5月(2019-05)公开的行,因此,如果在5月底之前的任何时候将某行转为草稿(而不是重新公开),则不需要。 For example: 例如:

id | post_id | status | date
-------------------------
 1 | 1       | draft  | 2019-03-25
 2 | 1       | public | 2019-04-02
 3 | 1       | draft  | 2019-05-25
 4 | 2       | draft  | 2019-03-10
 5 | 2       | public | 2019-04-01
 6 | 2       | draft  | 2019-06-01

The desired result for the above would return post_id 2 because its last status change prior to the end of May was to public . 上面的预期结果将返回post_id 2因为其5月底之前的最后状态更改已public

post_id 1 was put back in draft before the end of May, so it would not be included. 5月底之前将post_id 1重新放回草稿中,因此不会包含在内。

I'm not sure how to use the correct join or sub-queries to do this as efficiently as possible. 我不确定如何使用正确的联接或子查询来尽可能高效地执行此操作。

You seem to want the status as of 2019-05-31. 您似乎想要截至2019-05-31的状态。 A correlated subquery seems like the simplest solution: 相关子查询似乎是最简单的解决方案:

select t.*
from t
where t.date = (select max(t2.date)
                from t t2
                where t2.post_id = t.post_id and
                      t2.date <= '2019-05-31'
               );

To get the ones that are public, just add a WHERE condition: 要获取公开的内容,只需添加WHERE条件:

select t.*
from t
where t.date = (select max(t2.date)
                from t t2
                where t2.post_id = t.post_id and
                      t2.date <= '2019-05-31'
               ) and
      t.status = 'public';

For performance, you want an index on (post_id, date) . 为了提高性能,您需要在(post_id, date)上建立索引。

You can also phrase this using a JOIN : 您也可以使用JOIN来表达这一点:

select t.*
from t join
     (select t2.post_id, max(t2.date) as max_date
      from t t2
      where t2.date <= '2019-05-31'
      group by t2.post_id
     ) t2
     on t2.max_date = t.date
where t.status = 'public';

I would expect the correlated subquery to have better performance with the right indexes. 我希望相关的子查询在正确的索引下具有更好的性能。 However, sometimes MySQL surprises me. 但是,有时MySQL使我感到惊讶。

we need to determine whether 我们需要确定是否

  1. the status of each post_id is public prior to the month May (the subquery with max(date)), 每个post_id的状态在May (具有max(date)的子查询)之前是public
  2. any post_id exists with status not equals public within the month May , May内,任何post_id存在且状态不等于public
  3. and then exclude the post_id satisfying the matter 2. 然后排除满足此要求的post_id 2。

So, you can use : 因此,您可以使用:

select distinct t1.post_id
  from tab t1
where t1.post_id not in
    (
     select distinct t1.post_id
       from tab t1
       join
       (
        select post_id, max(date) as date
          from tab 
         where '2019-05-01'> date
         group by post_id ) t2
         on t1.post_id = t2.post_id 
      where t1.status != 'public' 
        and t1.date < '2019-06-01' 
        and t1.date > '2019-04-30'
);

+---------+
| POST_ID |
+---------+
|    2    |
+---------+

Demo 演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM