postgres:如何选择一个范围内的所有值?

时间:2019-07-17 03:57:02

标签: sql postgresql

我有一个表格test_table,看起来像这样:

     analysis_date      |      test_num
------------------------+--------------------
 2001-01-01             |                  1
 2001-01-01             |                  2
 2001-01-01             |                  3
 2001-01-02             |                  1
 2001-01-02             |                  2
 2001-01-02             |                  3
 2001-01-03             |                  1
 2001-01-03             |                  2
 2001-01-03             |                  8

我只想选择分析日期的值为test_num 1、2和3的行。查询不应返回anlysis_date 2001-01-03的行作为{{1}的行} =缺少3个

test_num

我知道 analysis_date | test_num ------------------------+-------------------- 2001-01-01 | 1 2001-01-01 | 2 2001-01-01 | 3 2001-01-02 | 1 2001-01-02 | 2 2001-01-02 | 3 查询,但这不能保证范围内的所有值都存在。

3 个答案:

答案 0 :(得分:2)

您可以尝试

SELECT * FROM test_table
   WHERE analysis_date 
              IN ( SELECT analysis_date
                         FROM test_table  where test_num IN (1,2,3)
                         group by analysis_date having 
                         count(DISTINCT test_num) = 3
                   )

DEMO

答案 1 :(得分:1)

您也可以使用exists

select * 
  from test_table t
 where exists ( select 1
                  from test_table  
                 where test_num in (1,2,3)
                   and analysis_date = t.analysis_date
                 group by analysis_date 
                having count(distinct test_num) = 3
               )

作为@Kaushik案的替代方案。

答案 2 :(得分:0)

如果希望原始行可能是三个,则最快的方法是存在的:

select t.*
from test_table t
where exists (select 1
              from test_table tt
              where tt.analysis_date = t.analysis_date and
                    tt.test_num = 1
             ) and
      exists (select 1
              from test_table tt
              where tt.analysis_date = t.analysis_date and
                    tt.test_num = 2
             ) and
      exists (select 1
              from test_table tt
              where tt.analysis_date = t.analysis_date and
                    tt.test_num = 3
             );

尤其是,这可以利用(analysis_date, test_num)上的索引。

也就是说,我想我更喜欢窗口函数。假设您在同一天没有重复测试:

select tt.*
from (select tt.*,
             count(*) filter (where test_num in (1, 2, 3)) over (partition by analysis_date) as cnt
      from test_table tt
     ) t
where cnt = 3;