Sqlite query all the missing ids - sql

I got two tables in my DB, users and gifts. The user table got id and data, the gifts table got gift_id, user_id and data.
gitst.user_id associated with users.id
How can I get all the user_id from gifts table that not appear in users table?

One way to do it is using the except operator.
select user_id from gifts
except
select id from users
Except gives you the difference of two sets.
Let's say set A = {1,2,3} B={3,4,5,6}.
A-B = {1,2} because 3 exists in both the sets and 1,2 exist in A but not in B
B-A = {4,5,6} 3 is common to both sets and 4,5,6 exist in B but not in A
You can also do
select user_id from gifts
where user_id not in (select id from users)
or
select user_id from gifts g
where not exists (select 1 from users where id = g.user_id)

select user_id from gifts not exists(select id from users)

Related

How to find common matches for different column values in SQL

I have the following table "Friends":
The goal is to find out how many users have the exact same list of friends.
In this case, the result would be user_id 1 and user_id 4 since both user 1 and user 4 are friends with "2" and "3".
I think I am on the right track by using the code below:
SELECT * FROM Friends A, Friends B WHERE A.friend_id=B.friend_id AND A.user_id <> B.user_id
However, I am not able to figure out how to finish the query so that it calculates the matching list of friends. Does anyone have any suggestions?
You didn't provide your SQL type.
For MySQL, you can group concat the friends for every user and cross by this value. The default is ",". Then join the same table to compare by the same list of friends.
SELECT t1.friends, t1.friends FROM
(
SELECT user_id,GROUP_CONCAT(friend_id) as friends
FROM friends
GROUP BY friend_id
) as t1
JOIN
(
SELECT user_id,GROUP_CONCAT(friend_id) as friends
FROM friends
GROUP BY friend_id
) as t2
on t1.friends = t2.friends

Joining on a table but only match if it has at least one row based on a condition

I'm trying to find all users who have at least 1 transaction that has the StoreLocationID=123.
The basic query to get the count of users is:
SELECT COUNT(*)
FROM Users u
The transaction table looks like:
Transactions
- ID
- UserID
- Amount
- Date
- StoreLocationID
How can I find ALL users who have at least 1 transaction where StoreLocationID=123.
I can join on the table, but I just need to know if there is at least 1 row with StoreLocationID=123.
You can use a correlated subquery with an exists condition:
select *
from users u
where exists (
select 1
from transactions t
where t.userID = u.userID
and t.StoreLocationID = 123
)
This will give you all users that have at least one transaction on in store 123.
If you just want to count of such users, then:
select count(*)
from users u
where exists (
select 1
from transactions t
where t.userID = u.userID
and t.StoreLocationID = 123
)
Or:
select count(distinct userID) from transactions where StoreLocationID = 123

Union Three or more tables with conditions

I need a help to solve some problem.
I have some table levelAsignment with columns level_id, store_id and user_id. For each user_id I can write a query to get his level_ids and store_ids.
Also I have a table stores.
I need to get for each store his level and count the users of the current level and store.
It's easy, but the problem is in storing data, Because in the levelAsignment table the user can set all stores for some operator level.
It looks like this:
level_id | store_Id | user_id
4 1 5
1 5 5
6 1
when store_id = 1 in the stores table it means all stores, so I need to show all stores except 1.
select * from stores where id != 1;
so I need an advice how to organize that.
I find different ways to solve the problem, but there were many unions and conditions.
This depends on how you are able to join the stores table
I think you should join level_assignment (where the store_id = 1) with all data in the stores table, but subquery where the outer query excludes the store_id = 1 column from the level assignment table. You may have to create a join column in temporary tables for the stores data. Then union the level_assignment table where store_id != 1
Example:
WITH get_all_stores_for_store_id_1 AS (
SELECT
a.level_assigment,
a.store_id,
b.store_id,
a.user_id
FROM level_assignment a
LEFT JOIN stores b ON a.join_column = b.join_column
WHERE a.store_id = 1)
SELECT
level_assignment,
b.store_id AS store_id,
user_id
FROM get_all_stores_for_store_id_1
UNION
SELECT
level_assignment,
store_id,
user_id
FROM level_assignment
WHERE store_id != 1
Does that make sense?
Thinking about how to join the data, we could do something like this:
Get the stores table and create a 1 column with a one in every row for the stores, so that we can then join all stores to the level_assignment table with store_id = 1:
WITH set_1_column_in_stores_table AS (
SELECT
1 AS join_id,
store_id,
FROM stores),
all_store_rows_get_all_stores AS (
SELECT
a.level_assigment,
a.store_id,
b.store_id,
a.user_id
FROM level_assignment a
LEFT JOIN set_1_column_in_stores_table b ON a.store_id= b.join_id
-- The above will join all stores where store_id = 1 in level_assigment
WHERE a.store_id = 1)
SELECT
level_assignment,
b.store_id AS store_id,
user_id
FROM all_store_rows_get_all_stores
UNION
SELECT
level_assignment,
store_id,
user_id
FROM level_assignment
WHERE store_id != 1

SQL Inner Join Two Foreign Keys

I have two tables (Users and Pairs). The Pairs table contains 3 columns, an ID and then a user1ID and user2ID.
Users
ID firstName surname
------------------------------
1043 john doe
2056 jane doe
Pairs
ID user1ID user2ID
------------------------------
1 1043 2056
I'm then looking at using a select statement to get the user details base on the ID of the Pairs table:
SELECT users1.*, users2.*
FROM Pairs
JOIN Users users1 ON Pairs.user1ID = users1.IDNumber
JOIN Users users2 ON Pairs.user2ID = users2.IDNumber
WHERE Pairs.ID = 1
Which returns the right details for the two users, however they're all on one row, how can I get it to return each user on a separate row as they are in the Users table?
SELECT users1.*, users2.*
FROM Pairs
JOIN Users
ON Pairs.user1ID = users.IDNumber
OR Pairs.user2ID = users.IDNumber
WHERE Pairs.ID = 1
Just use an OR statement in your ON condition instead of 2 joins.
IN will work also.
SELECT *
FROM Pairs p
JOIN Users u ON u.ID IN (p.user1ID, p.User2ID)
WHERE p.ID = 1

Select by frequency

I have two tables, like that:
users(id, name)
phones(user_id, number)
I'd like to select all user's names that are in more than three rows in the table phones. How can I do that?
Join the tables and add a having clause that limits the results returned by the count of the user_ids
select name,
count(user_id)
from users u
join phones p
on u.id = p.user_id
group by name
having count(user_id) > 3
SQL Fiddle: http://sqlfiddle.com/#!2/c5516/2
select name from user
join phones on id = user_id
Group By user_id
Having Count(number) > 3