Home > database >  How to join and count the results of two SQL queries on the same table
How to join and count the results of two SQL queries on the same table

Time:10-10

I have one table that contains all kind of metadata about customers. It is structured like this:

customer_id, metadata_id, text_value

I want to count all customers that have a specific text_value for metadata_id='metadata_1' and for whom an entry for metadata_id='metadata_2' exists.

customer_id metadata_id text_value
customer_1 metadata_1 yes!
customer_1 metadata_2 random value
customer_2 metadata_1 yes!
customer_2 metadata_2 never mind
customer_3 metadata_1 no!
customer_3 metadata_2 another value
customer_4 metadata_1 yes!

I can easily get the two parts:

SELECT customer_id
FROM my_table
WHERE metadata_id='metadata_1' AND text_value='yes!';

SELECT customer_id
FROM my_table
WHERE metadata_id='metadata_2';

But how do I combine them and count them?

Here customer_1 and customer_2 fulfil both conditions. So the answer for the example would be 2.

CodePudding user response:

You can use EXISTS operator as the following:

SELECT COUNT(*) AS CNT
FROM my_table T
WHERE metadata_id='metadata_1' AND text_value='yes!'
AND EXISTS(SELECT 1 FROM my_table D WHERE D.customer_id=T.customer_id AND D.metadata_id='metadata_2')

If there is a duplicate ids and and you want to count only distinct ids you can use COUNT(DISTINCT customer_id).

And if you want to get the customer ids:

SELECT customer_id
FROM my_table T
WHERE metadata_id='metadata_1' AND text_value='yes!'
AND EXISTS(SELECT 1 FROM my_table D WHERE D.customer_id=T.customer_id AND D.metadata_id='metadata_2')

See a demo.

CodePudding user response:

We mark the customer_id that follows condition one. Then we mark the customer_id that follows condition two and then we count the customer_id we have left.

select  count(distinct customer_id) as cnt
from   (
       select  *
               ,count(case when metadata_id = 'metadata_1' and text_value = 'yes!' then 1 end) over(partition by customer_id) as mrk1 
               ,count(case when metadata_id = 'metadata_2' then 1 end) over(partition by customer_id) as mrk2
       from    t
       ) t
where  mrk1 > 0 
and    mrk2 > 0
cnt
2

Fiddle

CodePudding user response:

A UNION should work I think

SELECT COUNT(customer_id)
FROM (
        SELECT customer_id
        FROM my_table
        WHERE metadata_id = 'metadata_1'
            AND text_value = 'yes!'
        UNION
        SELECT customer_id
        FROM my_table
        WHERE metadata_id = 'metadata_2'
    ) alpha;

CodePudding user response:

I think this should do it

;WITH
  T1
  AS
  (
    SELECT customer_id
    FROM my_table
    WHERE metadata_id='metadata_1' AND text_value='yes!'
  ),
  T2
  AS
  (
    SELECT customer_id
    FROM my_table
    WHERE metadata_id='metadata_2'
  )
  SELECT COUNT(1)
  FROM T1
    INNER JOIN
    T2 ON T1.customer_id = T2.customer_id

CodePudding user response:

you can use OR operator and merge your conditions.

SELECT
    COUNT(*)
FROM
    (
        SELECT
            customer_id
        FROM
            my_table
        WHERE
            ( ( metadata_id= 'metadata_1' AND text_value= 'yes!' )
              OR metadata_id= 'metadata_2' )
        GROUP BY
            customer_id
        HAVING
            COUNT(*) > 1
    );
  •  Tags:  
  • sql
  • Related