我在MariaDB(latest)中有一个表t,其中包括person_ID、date_1、date_2等列。它们分别包含人员ID和字符串日期。对于每个ID,只有一个date_1,但有多个date_2。行要么有date_1,要么有date_2,这就是我加入ID的原因。下面是表t的一个示例:
| 人员标识|日期_1|日期_2|
| - -|- -|- -|
| A级|- -|三个|
| A级|- -|五个|
| A级|一个|- -|
| 乙|- -|10个|
| 乙|- -|十四|
| 乙|五个|- -|
| C类|- -|十一|
| C类|- -|九个|
| C类|七个|- -|
创建并填写表格t:
CREATE TABLE t(
id SERIAL,
person_ID TEXT,
date_1 TEXT,
date_2 TEXT,
PRIMARY KEY (id)
);
INSERT INTO t (person_ID, date_2) VALUES ('A', 3);
INSERT INTO t (person_ID, date_2) VALUES ('A', 5);
INSERT INTO t (person_ID, date_1) VALUES ('A', 1);
INSERT INTO t (person_ID, date_2) VALUES ('B', 10);
INSERT INTO t (person_ID, date_2) VALUES ('B', 14);
INSERT INTO t (person_ID, date_1) VALUES ('B', 5);
INSERT INTO t (person_ID, date_2) VALUES ('C', 11);
INSERT INTO t (person_ID, date_2) VALUES ('C', 9);
INSERT INTO t (person_ID, date_1) VALUES ('C', 7);
SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
以下是两个子查询A和B的内部联接。查询A给出了一个不同的person_ID列表,其中包含date_1和date_1本身。另一方面,查询B应该给出一个不同的person_ID列表,其中包含date_2和MAX(date_2)。
SELECT A.person_ID, A.date_A, B.date_B, B.date_B - A.date_A AS diff FROM
(SELECT person_ID, date_1 AS date_A FROM t
WHERE date_1 >= 0) A
INNER JOIN
(SELECT person_ID, MAX(date_2) AS date_B FROM t
WHERE date_2 >= 0
GROUP BY person_ID) B
ON A.person_ID = B.person_ID
AND B.date_B > A.date_A
AND (B.date_B - A.date_A) <= 7
GROUP BY A.person_ID;
输出如下:
| 人员ID|日期_A|日期_B|差异|
| - -|- -|- -|- -|
| A级|一个|五个|四个|
| C类|七个|九个|2个|
但这将是期望的结果(忽略ID = B,因为diff = 9):
| 人员ID|日期_A|日期_B|差异|
| - -|- -|- -|- -|
| A级|一个|五个|四个|
| C类|七个|十一|四个|
我假设MAX(date_2)为person_ID = C给出9而不是11,因为该值是最后为date_2插入的。
您可以使用此链接亲自试用。
1条答案
按热度按时间yc0p9oo01#
稀疏表(带有NULL的行)使这个问题变得更加困难。
从一个子查询开始清理稀疏表。它生成一个结果集,其中包含空值的行被删除,生成如下所示的结果。
这会将每个人的单一
date_1
值放入具有date_2
值的列中。query的执行方式为:让我们将该子查询的输出命名为别名
detail
。您的业务逻辑需要非常常见的greatest-n-per-group查询模式。它需要检索每个
person_ID
中具有最大diff
的行(与diff <= 7
一样长)。使用该detail
子查询,我们可以更容易地编写逻辑。在结果集中,您希望每个person_ID
的行显示date_1
、date_2
并且diff
用于最大diff,但是不考虑diff
〉7的任何行。首先,写入another subquery,以找出每个
person_ID
的最大合格diff
值。然后将该子查询连接到详细信息,以获得所需结果集。
现在,我使用common table expression来编写此查询:来定义
detail
。该语法在MariaDB 10.2+(和MySQL 8+)中可用。将其组合在一起,下面是查询。总结:解决问题的步骤。
date_2
值的行中填充date_1
值来去除具有NULL值的输入行。person_ID
的最大合格diff
值。diff
列表重新连接到从表中,以提取从表中正确得行.专业提示不要关闭
ONLY_FULL_GROUP_BY
。你不想依赖MySQL / MariaDB的strange nonstandard extension to GROUP BY,因为它有时会产生错误的值。当它产生错误的值时,这是令人困惑的。