如何在MySQL中获得每种类型的最早

问题描述 投票:0回答:3

对于以下数据:

mysql> select * from policy_redeem_window;
+----+---------+-----------+----------+-------+---------------------+---------+---------------------+
| id | user_id | policy_id | delta_id | value | start_date          | state   | created             |
+----+---------+-----------+----------+-------+---------------------+---------+---------------------+
|  1 |       0 | policy1   | delta1   |  1.00 | 2019-12-11 14:22:21 | PENDING | 2019-12-11 14:22:21 |
|  2 |       0 | policy1   | delta2   |  1.00 | 2019-12-12 14:22:33 | PENDING | 2019-12-11 14:22:33 |
|  3 |       0 | policy2   | delta3   |  1.00 | 2019-12-11 14:22:45 | PENDING | 2019-12-11 14:22:45 |
|  4 |       0 | policy2   | delta4   |  1.00 | 2019-12-12 14:23:08 | ACTIVE  | 2019-12-11 14:23:08 |
|  6 |       0 | policy2   | delta5   |  1.00 | 2019-12-11 14:23:37 | ACTIVE  | 2019-12-11 14:23:37 |
+----+---------+-----------+----------+-------+---------------------+---------+---------------------+
5 rows in set (0.00 sec)

我正在尝试每个policy_id仅获得一行,其中每一行都是最早的start_date

我已经尝试过以下查询:

select * 
from policy_redeem_window 
where user_id = 0 
and state in ('ACTIVE', 'PENDING') 
group by policy_id 
order by start_date desc;

但是这给了我以下错误:

SELECT列表的表达式#1不在GROUP BY子句中,并且包含未聚合的列'admiral.policy_redeem_window.id',该列在功能上不依赖于GROUP BY子句中的列;这与sql_mode = only_full_group_by

不兼容

我在哪里错了?

mysql sql greatest-n-per-group
3个回答
1
投票

一个常见的解决方法是通过聚合联接,这使您可以为每个组获取完整的行:

SELECT t.*
FROM (
    SELECT policy_id, MIN(start_date) AS first_date
    FROM policy_redeem_window
    WHERE user_id = 0
    AND state IN ('ACTIVE', 'PENDING')
    GROUP BY policy_id
) AS g
JOIN policy_redeem_window AS t ON g.policy_id = t.policy_id AND g.first_date = t.start_date

0
投票

使用NOT EXISTS

select p.* from policy_redeem_window p
where p.user_id = 0 
and p.state in ('ACTIVE', 'PENDING')
and not exists (
  select 1 from policy_redeem_window 
  where policy_id = p.policy_id and user_id = p.user_id and state in ('ACTIVE', 'PENDING') 
  and start_date < p.start_date 
);

请参见demo。对于带ROW_NUMBER()的MySql 8.0 +:

select p.id, p.user_id, p.policy_id, p.delta_id, p.value, p.start_date, p.state, p.created
from (
  select *, row_number() over (partition by policy_id order by start_date) rn
  from policy_redeem_window
  where user_id = 0 and state in ('ACTIVE', 'PENDING')
) p
where p.rn = 1;

请参见demo。结果:

| id  | user_id | policy_id | delta_id | value | start_date          | state   | created             |
| --- | ------- | --------- | -------- | ----- | ------------------- | ------- | ------------------- |
| 1   | 0       | policy1   | delta1   | 1     | 2019-12-11 14:22:21 | PENDING | 2019-12-11 14:22:21 |
| 3   | 0       | policy2   | delta3   | 1     | 2019-12-11 14:22:45 | PENDING | 2019-12-11 14:22:45 |

-1
投票

您需要在group-by子句中不在的每一列上放置一个聚合函数。也就是说,因为您需要为多个返回的结果集选择一个标量值才能返回。

select policy_id, min(start_date)
from policy_redeem_window 
where user_id = 0 
and state in ('ACTIVE', 'PENDING') 
group by policy_id 
order by start_date desc;
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.