考虑两个表:
Foo:
id INT,
name VARCHAR
Bar:
id INT,
foo_id INT REFERENCES Foo(id),
event SET('hit','miss'),
ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
每个Foo项目可以有多个Bar事件。 如何在特定日期时间之后查询拥有条形码事件的Foo项目,但在该日期时间之前没有条形码事件?
例如,考虑:
Foo id=1:
hit 2014-01-21
hit 2014-01-22
hit 2014-01-23
Foo id=2:
hit 2014-01-17
hit 2014-01-19
hit 2014-01-21
Foo id=3:
hit 2014-01-14
hit 2014-01-15
hit 2014-01-18
Foo id=4:
hit 2014-01-21
hit 2014-01-22
hit 2014-01-24
我想仅查询2014-01-20
之后或之后点击的那些Foo项,因此应返回ID 1
和4
。
我尝试将Bar
表加入到自身中,使用以下几种变体:
SELECT
b1.id
FROM
Bar b1 JOIN Bar b2 using (foo_id)
WHERE
b1.ts > '2014-01-20';
但是,我没有看到如何用WHERE子句来排除2014-01-20
之前任何日期的任何组合。
答案 0 :(得分:2)
SELECT Foo.*
FROM Foo JOIN Bar ON Bar.foo_id = Foo.id
GROUP BY Foo.id
HAVING MIN(Bar.ts) >= '2014-01-20'
或者:
SELECT Foo.*
FROM Foo JOIN (
SELECT foo_id id, MIN(ts) min_ts
FROM Bar
GROUP BY id
) t USING (id)
WHERE t.min_ts >= '2014-01-20'
或者:
SELECT Foo.*
FROM Foo JOIN Bar ON Bar.foo_id = Foo.id
GROUP BY Foo.id
HAVING SUM(Bar.ts >= '2014-01-20')
AND NOT SUM(Bar.ts < '2014-01-20')
或者:
SELECT *
FROM Foo
WHERE EXISTS (
SELECT *
FROM Bar
WHERE Bar.foo_id = Foo.id
AND Bar.ts >= '2014-01-20'
)
AND NOT EXISTS (
SELECT *
FROM Bar
WHERE Bar.foo_id = Foo.id
AND Bar.ts < '2014-01-20'
)
或者:
SELECT b1.foo_id
FROM Bar b1 LEFT JOIN Bar b2
ON b2.foo_id = b1.foo_id
AND b2.ts < '2014-01-20'
WHERE b1.ts >= '2014-01-20'
AND b2.foo_id IS NULL
GROUP BY b1.foo_id