skip to Main Content

Let’s say I have the following data table:

id | data_1 | data_2 | category
1  |    a   |    A   |    1    
2  |    a   |    A   |    1    
3  |        |    B   |    2    
4  |    b   |    B   |    2    
5  |    b   |    B   |    2    
6  |    c   |        |    3    
7  |    c   |        |    3    
8  |    c   |    C   |    3    
9  |        |    D   |    4 
10 |    d   |        |    4    
11 |    d   |    D   |    4    
12 |    d   |    D   |    4    
13 |    e   |    E   |    5    
14 |    e   |    E   |    5     
15 |    f   |    F   |    6      

and a list of (record) id as input:

1, 5, 12, 13, 14

I’d like to make a query which returns all those categories which are "referenced" by any of the record in the input list and the referenced category is "complete".

By

  • referenced category I mean that at least one record from the input list belongs to that category
  • complete category I mean that all record that belongs to that category has value (i.e. not NULL or empty string) in both data_1 and data_2 column. (So in the example table category 1, 5 and 6 is complete)

So for the example table and input the result would be:

category
   1    
   5    

(And for an input of 4, 5, 6 the result would be NULL or empty list)

Is it possible to make single query for this?

(fiddle)

2

Answers


  1. select distinct category from tbl 
    where category not in (
    select category from tbl
    where data_1 is null or data_1 = ''
    or  data_2 is null or data_2 = '')
    

    Fixed using your fiddle!

    Login or Signup to reply.
  2. First, query ids where category is completed:

    select
        category,
        array_agg(id) as ids
    from tbl
    group by category
    having bool_and(nullif(data_1, '') || nullif(data_2, '') is not null) 
    order by category;
    
     category |   ids
    ----------+---------
            1 | {1,2}
            5 | {13,14}
            6 | {15}
    (3 rows)
    

    Use this as a derived table to search ids matching the input list:

    select category
    from (
        select
            category,
            array_agg(id) as ids
        from tbl
        group by category
        having bool_and(nullif(data_1, '') || nullif(data_2, '') is not null) 
        ) s
    where ids && array[1, 5, 12, 13, 14] -- input parameter
    order by category;
    
     category
    ----------
            1
            5
    (2 rows)
    

    Test it in db<>fiddle.

    Alternative solution using the bool_and() aggregate as a window function:

    select distinct category
    from (
        select 
            id, 
            category,
            bool_and(nullif(data_1, '') || nullif(data_2, '') is not null) over w as completed
        from tbl
        window w as (partition by category)
        ) s
    where completed
    and id = any(array[1, 5, 12, 13, 14]) -- input parameter
    order by category;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search