有一个关联日期和名称的列表,我想选择:当日期之间的差异超过 1 个月时,名称具有多个日期的所有行。
例如:只有下面标有的条目 \*this*\
CREATE TABLE IF NOT EXISTS myTab (
id SERIAL PRIMARY KEY,
dateID DATETIME DEFAULT 0,
name VARCHAR(512)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO myTab
(dateID, name)
VALUES
("20140811","Emmy"), /*this*/
("20140922","Emmy"), /*this*/
("20150920","Emmy"), /*this*/
("20150922","Emmy"),
("20140722","Dave"),
("20140613","Stan"),
("20140622","Stan"), /*this*/
("20151020","Stan"), /*this*/
("20140305","Lora"),
("20140310","Lora");
Run Code Online (Sandbox Code Playgroud)
换句话说,标准是:
IF diff > 1 MONTH THEN select both, ELSE skip
这是一个工作示例以及我基于SO 的另一个答案的尝试:
+1 id
。它们也不按日期插入。在上面的例子中,这样做只是为了可读性。在我真正的问题中,情况并非如此!/*this_EXRA*/
在上面的示例中添加了一个额外的条件。第 3stan
行距第 2 行不到 1 个月,但使用第 4 行对其进行验证。因此,只有当它同时验证它们时才应该选择它。所以我想这意味着逐行循环并每次与上一个和下一个进行比较。这个逻辑乍一看很简单,但要做好却相当复杂。
让我们先有一个可行的解决方案,然后再考虑性能。在reextester.com 上测试:
SELECT t.id, t.dateID, t.name
FROM myTab AS t
WHERE
( SELECT b.dateID
FROM myTab AS b
WHERE t.name = b.name
AND b.dateID < t.dateID
ORDER BY b.dateID DESC
LIMIT 1
) + INTERVAL 1 MONTH <= t.dateID
OR
t.dateID + INTERVAL 1 MONTH <=
( SELECT b.dateID
FROM myTab AS b
WHERE t.name = b.name
AND t.dateID < b.dateID
ORDER BY b.dateID ASC
LIMIT 1
)
;
Run Code Online (Sandbox Code Playgroud)
关于效率:查询的性能会很差。索引(name, dateID, id)
会有所帮助,但查询仍需要为表的每一行执行 2 个子查询。
归档时间: |
|
查看次数: |
4523 次 |
最近记录: |