SQL QUERY ON 2 TABLES WITH EXCLUSION - sql

I'm looking for a sql query to select IDs from the "product" table for "user" 1 that don't appear in the "Fake" table in the "product_id" field for "customer _id" 20 (for example). I hope to be clear enough in my request. Thanks for your help

Thanks XQbert. I think I succeeded thanks to your advice. Thank you
SELECT P.*, U.name
FROM product P
INNER JOIN user U
ON P.user_id = U.id
WHERE U.id= '1'
AND NOT EXISTS
(SELECT F.*
FROM fake F
INNER JOIN customer C
ON F.customer_id = C.id
WHERE P.id = F.product_id
AND C.customer_id = 20)

Related

SQL to HiveQL conversion

I have this SQL query and I am trying to convert it so that it can be run on HiveQL 2.1.1.
SELECT p.id FROM page p, comments c, users u,
WHERE c.commentid= p.id
AND u.id = p.creatorid
AND u.upvotes IN (
SELECT MAX(upvotes)
FROM users u WHERE u.date > p.date
)
AND EXISTS (
SELECT 1 FROM links l WHERE l.relid > p.id
)
This does not work on Hive QL, as it has more than 1 SubQuery (which is not supported)
EXISTS or IN replacements from SQL to Hive SQL are done like this:
WHERE A.aid IN (SELECT bid FROM B...)
can be replaced by:
A LEFT SEMI JOIN B ON aid=bid
But I can`t come up with a way to do this with the additional MAX() function.
Use standard join syntax instead of comma separated :
SELECT p.id
FROM page p INNER JOIN
comments c
ON c.commentid= p.id INNER JOIN
users u
ON u.id = p.creatorid INNER JOIN
links l
ON l.relid > p.id
WHERE u.upvotes IN (SELECT MAX(upvotes)
FROM users u
WHERE u.date > p.date
);
I am not sure what the upvotes logic is supposed to be doing. The links logic is easy to handle. Hive may handle this:
SELECT p.id
FROM page p JOIN
comments c
ON c.commentid = p.id JOIN
users u
ON u.id = p.creatorid CROSS JOIN
(SELECT MAX(l.relid) as max_relid
FROM links l
) l
WHERE l.max_relid > p.id AND
u.upvotes IN (SELECT MAX(upvotes)
FROM users u
WHERE u.date > p.date
);

SQL LEFT JOIN for joining three tables but one with to exclude content

I have 3 tables
STUDENTS
FEES_PAID
SUSPENDED
I want to get the details of the students who have paid the fees but not from SUSPENDED.
SELECT
ID
FROM
STUDENTS s
LEFT JOIN
SUSPENDED p ON s.ID = p.ID
INNER JOIN
FEES_PAID f ON f.ID = s.ID
WHERE
s.ID IS NULL
Unfortunately this does not work. Can any one suggest an efficient query?
Thanks in advance
You need to check if the second table is missing from the LEFT JOIN. So, you need to look at a column in that table. Change the WHERE to:
WHERE p.ID IS NULL
Alternatively, use NOT EXISTS:
SELECT s.ID
FROM STUDENTS s INNER JOIN
FEES_PAID f
ON f.ID = s.ID
WHERE NOT EXISTS (SELECT 1 FROM SUSPENDED p WHERE s.ID = p.ID);
Note that for both these queries, you will need to qualify the ID in the SELECT to specify the table where it comes from.
This should work:
SELECT
s.ID
FROM
STUDENTS s
LEFT JOIN
SUSPENDED p
ON s.ID=p.ID
INNER JOIN
FEES_PAID f
ON f.ID= s.ID
WHERE
p.ID IS NULL

How do I match against multiple conditions on a table join?

I have two tables:
users attributes
id|name id|name|user_id
------- ---------------
1 |foo 1 |bla | 1
2 |bar 1 |blub| 1
1 |bla | 2
How do I create a query gives users with both the "bla" AND "blub" attributes?
In this case it should only return the user "foo".
I know that the data is not normalized.
SELECT u.*, a.id, b.Id, a.name, b.name FROM users u
JOIN attributes a
ON a.User_id = u.User_id AND a.name = 'bla'
JOIN attributes b
ON u.User_Id = b.User_id AND b.name = 'blub'
Assuming an attribute association to a user is unique...
if you need 3 conditions to be true add the conditions to the in and adjust count up 1.
SELECT u.name
FROM users u
INNER JOIN attributes a on A.user_Id = u.id
WHERE a.name in ('bla','blub')
GROUP by u.name
HAVING count(*)=2
and if you don't have an unique association, or you need to join to another table you could always do...
SELECT u.name
FROM users u
INNER JOIN attributes a on A.user_Id = u.id
WHERE a.name in ('bla','blub')
GROUP by u.name
HAVING count(distinct A.name)=2
for a slight performance hit. but this allows you to join and get back additional fields which others have indicated was a detriment to this method.
This allows for scaling of the solution instead of incurring the cost of joining each time to different tables. In addition, if you needed thirty-something values to associate, you may run into restrictions on the number of allowed joins.
SELECT U.NAME
FROM USERS U
INNER JOIN
ATTRIBUTES A1
ON U.ID = A1.USER_ID
INNER JOIN
ATTRIBUTES A2
ON U.ID = A2.USER_ID
WHERE A1.NAME = 'bla'
AND A2.NAME = 'blub'
You can use the INTERSECT operator
SELECT
u.id
,u.name
FROM users AS u
INNER JOIN attributes AS a
ON u.id = a.user_id
WHERE a.name = 'bla'
INTERSECT
SELECT
u.id
,u.name
FROM users AS u
INNER JOIN attributes AS a
ON u.id = a.user_id
WHERE a.name = 'blub'
;
Here is a demo on SQL Fiddle: http://sqlfiddle.com/#!6/68986/5
More info on SET operations in SQL: http://en.wikipedia.org/wiki/Set_operations_(SQL)
SELECT u.name
FROM attributes a
JOIN users u
ON u.id = a.user_id
WHERE a.name IN ('bla','bulb')

How can I exclude another value from a column in joined table SQL

I thought this would be a straightforward query to write, but it's proving to be much trickier to achieve than I first thought.
Any help would be much appreciated - it's driving me up the wall :)
I have two tables, one USERS the second; PURCHASED PRODUCTS. A user can have multiple products in the PRODUCTS table.
I have a joined query where I return a list of users that have a specific product - so far so good.
Now here's the problem:
I want to exclude USERS that have another specific product.
Therefore, only return users that have product 1001, NOT users that have both products 1001 AND 1002 in the PRODUCTS table.
SELECT u.*
FROM users u
INNER JOIN purchased_products p
ON u.user_id = p.user_id
AND p.product_id = 1001
WHERE NOT EXISTS(SELECT 1
FROM purchased_products p2
WHERE p2.product_id = 1002
AND p2.user_id = u.user_id)
A slightly different approach:
SELECT u.user_id
FROM users u
JOIN purchased_products p
ON u.user_id = p.user_id AND
p.product_id in (1001, 1002)
GROUP BY u.user_id
HAVING COUNT(DISTINCT p.product_id) = 1 AND
MIN(p.product_id) = 1001
SELECT * from `user`
LEFT JOIN `product` on `user`.`id` = `product`.`user_id`
WHERE `product`.`id` = <w1st_product_id>
AND `user`.`id` NOT IN (
SELECT user_id
FROM product
WHERE product.id = <2nd_product_id>
)
SELECT * from user U
where (select count(*) from product P where P.user_id=U.user_id)=1
only return users that have product 1001, NOT users that have both products 1001 AND 1002 in the PRODUCTS table.
If you're using SQL Server 2005 or later, you can use
SELECT U.Id
FROM [User] U INNER JOIN Product P ON U.Id = P.UserId AND P.ProductId = 1001
EXCEPT
SELECT U.Id
FROM [User] U INNER JOIN Product P ON U.Id = P.UserId AND P.ProductId = 1002
which, as the word "EXCEPT" suggests, will return the ids for users that have product 1002, except if they also have product 1002.

DB2 SQL count in join or where clause

This is probably an amateur question but I'm an amateur ! ;o)
I have several tables: Account table, Officer table, Location table, Web table...
The Officer table doesn't give me the number of officers per account.
I need to retrieve only the accounts that have more than 20 officers.
Should I use the COUNT ? If so, how ?
Your help is greatly appreciated.
Thanks.
Pat
Update:
select a.id, a.eff-date, l.address, l.city, c.phonenumber
from Account a
left outer join location l on a.id = l.id
left outer join contact c on a.id = c.id
where a.id in (
select a.id
from Account a
inner join Officer ao on a.id = ao.id
group by a.id
having count(*) > 20
)