SQL选择计数(*)>最小数
我有两张桌子。其中一个门店的位置:SQL选择计数(*)>最小数,sql,postgresql,select,Sql,Postgresql,Select,我有两张桌子。其中一个门店的位置: TABLE location ( ID serial PRIMARY KEY, name text NOT NULL, description text NOT NULL ); 每个位置都有多行数据: TABLE data( ID smallint
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
GROUP BY location.id
HAVING MIN(data.date) <= '$start_date'
AND
MAX(data.date) >= '$end_date'
AND
(SELECT COUNT(*) FROM data WHERE data.date >= '$start_date' AND data.date <= '$end_date') >= '$min'
ORDER BY location.ID
数据:
如果我搜索数据在2001-01-01和2001-01-07之间且至少有6个数据值的所有位置,它应该只返回位置1 ID=1。不应返回第二个位置ID=2,因为它在所需时间段内没有所需数量的值。这是我的答案的新版本,因为我误解了“跨越”。我对这个问题的解释仍然是,在计算价值时,我们应该只在给定的时间内进行计算
SELECT l.id, l.name
FROM location l
JOIN location_data d
ON l.id = d.id
GROUP BY l.id, l.name
HAVING MIN(d.date) <= '2017-01-01'
AND MAX(d.date) >= '2017-12-31'
AND (SELECT COUNT(b.id)
FROM location_data b
WHERE b.date BETWEEN '2017-01-01' AND '2017-12-31'
AND b.id = l.id) >= 2
我在测试数据库中将表数据重命名为location_data,但这可能很明显:首先,应该将日期等值作为参数而不是字符串传递。其次,COUNT返回一个数字,因此比较应该是一个数字,而不是一个字符串 你应该能够做你想做的事。一种方法是:
SELECT l.ID, l.name
FROM location l JOIN
data d
ON d.id = l.id
GROUP BY l.id, l.name
HAVING MIN(d.date) <= '$start_date' AND
MAX(d.date) >= '$end_date' AND
COUNT(*) >= $min
ORDER BY l.ID;
这个问题在我看来已经很清楚了。我不知道PostreSQL,所以我只是问:你确定这个查询有效吗?我关心分组条款;在Oracle中,它应该包含SELECT中包含的所有列,否则将失败。我相信至少在PostgreSQL中也是如此,这是我在SQL Fiddle上所经历的。这也没有实现用户描述的逻辑。@Littlefoot,选择和分组方式应该匹配是对的。我会更新我的回复。@GordonLinoff,你能详细说明一下吗?@JoakimDanielson。这仅确定两个限制之间是否有日期。很明显,问题是检查周期前后的日期。
SELECT l.id, l.name
FROM location l
JOIN location_data d
ON l.id = d.id
GROUP BY l.id, l.name
HAVING MIN(d.date) <= '2017-01-01'
AND MAX(d.date) >= '2017-12-31'
AND (SELECT COUNT(b.id)
FROM location_data b
WHERE b.date BETWEEN '2017-01-01' AND '2017-12-31'
AND b.id = l.id) >= 2
SELECT l.ID, l.name
FROM location l JOIN
data d
ON d.id = l.id
GROUP BY l.id, l.name
HAVING MIN(d.date) <= '$start_date' AND
MAX(d.date) >= '$end_date' AND
COUNT(*) >= $min
ORDER BY l.ID;