Sql - Filtering on certain category

时间:2018-02-03 09:22:58

标签: sql postgresql where-clause

I am trying to write sql that would give me count of unique devices which appeared in category 'blue' and 'red' but not in any other category.

Below is my simple example. Answer for this question would be 3 devices (device 1, 2, 5).

If anyone could give me a tip, I would much appreciated. Thank you.

 device | category 
--------+----------
      1 | blue
      2 | red
      3 | black
      4 | yellow
      4 | blue
      5 | red
      5 | blue

3 个答案:

答案 0 :(得分:3)

Use bool_and():

with my_table(device, category) as (
values 
    (1, 'blue'),
    (2, 'red'),
    (3, 'black'),
    (4, 'yellow'),
    (4, 'blue'),
    (5, 'red'),
    (5, 'blue')
)

select device, bool_and(category in ('red', 'blue'))
from my_table
group by device
order by device;

 device | bool_and 
--------+----------
      1 | t
      2 | t
      3 | f
      4 | f
      5 | t
(5 rows)

Your query may look like this:

select device
from my_table
group by device
having bool_and(category in ('red', 'blue'))
order by device;

答案 1 :(得分:1)

One approach is to join your table to an aggregation query which identifies matching devices.

WITH cte AS (
    SELECT Device
    FROM yourTable
    GROUP BY Device
    HAVING SUM(CASE WHEN category NOT IN ('blue', 'red') THEN 1 ELSE 0 END) = 0
)

SELECT t1.Device, t1.Category
FROM yourTable t1
INNER JOIN cte t2
    ON t1.Device = t2.Device;

We can also use SUM as an analytic function:

SELECT Device, category
FROM
(
    SELECT Device, category,
        SUM(CASE WHEN category NOT IN ('blue', 'red') THEN 1 ELSE 0 END) OVER
            (PARTITION BY Device) color_sum
    FROM yourTable
) t
WHERE color_sum = 0;

Demo

答案 2 :(得分:0)

select distinct device from Test
where category in ('blue','red')
except
select distinct device from Test
where category in (select distinct category from test
                     where category not in ('blue','red'))

或者如果你需要数:

select count(*)
from
(select distinct device from Test
where category in ('blue','red')
except
select distinct device from Test
where category in (select distinct category from test
                     where category not in ('blue','red'))) a