使用WHERE子句和DISTINCT ON

时间:2016-07-21 13:43:54

标签: sql postgresql

我有以下两个postgresql表:

table: daily

id   date         close   symbol_id
1    2016-05-01   80      65
2    2016-05-01   75      67
3    2016-05-01   95      45
4    2016-05-02   11      65
5    2016-05-02   48      67
6    2016-05-02   135     45
7    2016-05-03   18      65
8    2016-05-03   82      67
9    2016-05-03   107     45
10   2016-05-04   29      65

table: symbol

id   symbol
65   abc
67   xyz
45   jkl

我需要为每个符号的最新日期选择symbols值小于100的所有close。根据示例,并非所有符号都具有相同的最新日期。

当我不使用WHERE子句时,以下查询为我提供了正确的数据:

SELECT DISTINCT ON (daily.symbol_id) symbol.symbol, daily.close, daily.date
FROM daily JOIN symbol ON daily.symbol_id = symbol.id
--WHERE daily.close < 100
ORDER BY daily.symbol_id, daily.date DESC

Result:

symbol   close   date
abc      29      2016-05-04
xyz      82      2016-05-03
jkl      107     2016-05-03

当我取消注释WHERE子句时,问题就出现了。期望的结果是从列表中删除符号jkl,因为该符号在其最新日期的close值不是&lt; 100.然而,这就是:

symbol   close   date
abc      29      2016-05-04
xyz      82      2016-05-03
jkl      95      2016-05-01

2 个答案:

答案 0 :(得分:1)

您可以将现有查询移至子查询,然后使用where条件进行过滤。

select * 
from (
    select distinct on (d.symbol_id) s.symbol, d.close, d.date
    from daily d 
        join symbol s on d.symbol_id = s.id
    order by daily.symbol_id, daily.date desc
) t
where close < 100

这是使用windows function的另一个类似选项,例如row_number

select *
from (
    select d.symbol_id, s.symbol, d.close, d.date,
           row_number() over (partition by d.symbol_id order by d.date desc) rn
    from daily d 
        join symbol s on d.symbol_id = s.id
    ) t
where rn = 1 and close < 100

答案 1 :(得分:0)

代码未经过测试,只是为了展示想法

首先进行查询以获取每个符号的最新日期。然后进行连接以过滤掉最新的行,您可以安全地应用close&lt; 100 where子句。

SELECT DISTINCT ON(symbol) * FROM (
SELECT MAX(d1.date) latest FROM daily d1 GROUP BY d1.symbol_id
INNER JOIN daily d2 ON latest = d2.date AND d1.symbol_id = d2.symbol_id) t
WHERE close <100