Home > OS >  How to make a query that filter out two AND conditions on same column
How to make a query that filter out two AND conditions on same column

Time:11-06

Write a query that returns all pages that have been visited by at least one child (demo='child') and ALSO has been visited by at least one person aged 18-25 (demo='18-25'). Your query should return a set of urls.

I am not sure how to write a query that filters out results based on Two AND statements on the same column and it returns out an empty set.

These are the two tables:

User

uid ip demo
A 001 child
B 002 18-25

Visit

url dt uid src rev
A01 1890-05-14 A A02 10
A01 002 B A03 15
Select distinct V.url
from Visit V, [User] Z, [User] F
WHERE V.uid = Z.uid AND V.uid = F.uid
AND Z.demo = 'child' AND F.demo = '18-25'

This above code returns me an empty set.

I want it to return A01 as the url

CodePudding user response:

First, you don't need to use User table twice in the select expression.

I think it can be solved by using nested queries or as called subquery.

In explanation: first you will query the items match the first condition (demo='child') then you will search on the results for the items that also match the second condition (demo='18-25').

Your code will be like this:

Select distinct V.url
from Visit V, [User] Z
WHERE V.uid = Z.uid AND Z.demo = 'child'
AND V.url IN (Select distinct V1.url
from Visit V1, [User] Z1
WHERE V1.uid = Z1.uid AND Z1.demo = '18-25')

CodePudding user response:

It looks like you can JOIN on the User table twice: once to find a user that is "18-25", and another to find a user that is a "child". If you find both of those (as determined by the WHERE clause) then the Visit record will be included in the results:

SELECT
  DISTINCT(V.url)
  FROM
    Visit V
  LEFT JOIN User U ON (V.uid = U.uid AND U.demo = '18-25')
  LEFT JOIN User U2 on (V.uid = U2.uid AND U2.demo = 'child')
  WHERE
    U.uid IS NOT NULL AND U2.uid IS NOT NULL

CodePudding user response:

You don't have to join User table twice and please use the more recommended JOIN operator over comma-join. To get the result you want, you can either use OR on demo or since the data is specific, you can try IN(). Consider these two query example:

/*Query 1*/

SELECT DISTINCT V.url
  FROM Visit V 
   JOIN User U
    ON V.uid = U.uid 
WHERE (U.demo = 'child' OR U.demo = '18-25');

/*Query 2*/

SELECT DISTINCT V.url
  FROM Visit V 
   JOIN User U
    ON V.uid = U.uid 
WHERE U.demo IN ('child','18-25');

Check the demo fiddle

CodePudding user response:

One way is to join the users, GROUP BY the URL, sum the occurrences of children and 18 to 25 year olds and check that these sums each exceed 0 in a HAVING clause.

SELECT v.url
       FROM Visit v
            INNER JOIN User u
                       ON v.uid = u.uid
       GROUP BY v.url
       HAVING sum(CASE
                    WHEN u.demo = 'child' THEN
                      1
                    ELSE
                      0
                  END) > 0
              AND sum(CASE
                        WHEN u.demo = '18-25' THEN
                          1
                        ELSE
                          0
                      END) > 0;

(Note: In MySQL you don't need the CASE expressions but could directly use the Boolean = expressions. But a CASE doesn't harm there either and with a CASE it'll also work in other DBMS. And since it's not entirely clear which DBMS you use a CASE expression is a safer bet.)

Another approach is to use a conjunction of EXISTS' and correlated subqueries that join the users to the visits and picks the record with the URL and demo in question. It would help if you already had a table with only the URLs. I'll simulate that with a derived table aliased x.

SELECT x.url
       FROM (SELECT DISTINCT
                    v.url
                    FROM Visit v) x
            WHERE EXISTS (SELECT *
                                 FROM Visit v
                                      INNER JOIN User u
                                                 ON u.uid = v.uid
                                 WHERE v.url = x.url
                                       AND u.demo = 'child')
                  AND EXISTS (SELECT *
                                     FROM Visit v
                                          INNER JOIN User u
                                                     ON u.uid = v.uid
                                     WHERE v.url = x.url
                                           AND u.demo = '18-25');
  • Related