SQL根据另一列中的值从一列中选择值

问题描述 投票:1回答:5

我有两张桌子。一个存储“位置”:

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测试,而不是对每个单独的位置应用,即测试需要应用于每个位置,并且仅返回通过测试的那些位置。

有什么建议?

sql postgresql join where
5个回答
3
投票

只按位置聚合,然后从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;

1
投票

当您说跨越给定时期时,为什么不使用如下所示的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;

请注意,这两个日期都包含在内


0
投票

您可以加入这些值的查询结果,并在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;

只是为了澄清 - 我知道你想得到所有datalocations在那些时间跨度有data(这个例子暗示这是你想要的)

如果你想获得在时间范围内“发生”的所有data,这不是你的解决方案,你想要@ jusermar10或@Yogs提供的between解决方案


0
投票

您可以使用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

0
投票

当你说跨越给定时期时,我想你的意思是只输出那些在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;
© www.soinside.com 2019 - 2024. All rights reserved.