我有两张桌子。一个存储“位置”:
TABLE location (
ID serial PRIMARY KEY,
name text NOT NULL,
description text NOT NULL
);
每个位置都有许多行“数据”:
TABLE data(
ID smallint REFERENCES location(ID),
date date,
rainfall int
);
我想找到所有具有跨越给定时期的“数据”的位置。我试过这个:
SELECT location.ID, location.name FROM location
JOIN data ON data.id = location.id
WHERE (SELECT MIN(data.date) FROM data) <= '$start_date'
AND
(SELECT MAX(data.date) FROM data) >= '$end_date'
ORDER BY location.ID;
但它似乎对所有数据应用MIN和MAX测试,而不是对每个单独的位置应用,即测试需要应用于每个位置,并且仅返回通过测试的那些位置。
有什么建议?
只按位置聚合,然后从HAVING
子句断言最小值/最大值:
SELECT
l.ID,
l.name
FROM location l
INNER JOIN data d
ON d.id = l.id
GROUP BY
l.ID
HAVING
MIN(data.date) <= '$start_date' AND
MAX(data.date) >= '$end_date'
ORDER BY
l.ID;
当您说跨越给定时期时,为什么不使用如下所示的between
SELECT location.ID, location.name FROM location location
JOIN data d ON d.id = location.id
WHERE d.date between '$start_date' AND '$end_date'
ORDER BY location.ID;
请注意,这两个日期都包含在内
您可以加入这些值的查询结果,并在where
条件中使用它
SELECT location.ID, location.name FROM location
JOIN data ON data.id = location.id
JOIN (
SELECT MIN(date) AS _min,MAX(date) AS _max,id
FROM data
GROUP BY id
) T ON T.id = location.id
WHERE T._min <= '$start_date' AND T._max >= '$end_date'
ORDER BY location.ID;
只是为了澄清 - 我知道你想得到所有data
为locations
在那些时间跨度有data
(这个例子暗示这是你想要的)
如果你想获得在时间范围内“发生”的所有data
,这不是你的解决方案,你想要@ jusermar10或@Yogs提供的between
解决方案
您可以使用between子句来获得所需的结果
SELECT l.ID, l.name FROM location l
inner JOIN data d ON d.id = l.id
WHERE d.date between '$start_date' and '$end_date' group by l.id
当你说跨越给定时期时,我想你的意思是只输出那些在data.date
和$start_date
之间拥有所有$end_date
的位置。
在这种情况下,此查询应该工作:
SELECT location.ID, location.NAME FROM locations, data
WHERE locations.ID=data.ID
GROUP BY locations.ID
HAVING min(data.date) >= '$start_date' and max(data.date) <= $end_date;