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;