select id not exist in other table, additional condition - sql

im intend to return i.e an id where it doesn't exist in other table.(e.g. transactions), with additional condition
users table
transactions table
aim was return id and name from users table which do not exist in transactions table, with join in users.id to transactions.investor_id (23xx) and join in users.id to transactions.borrower_id (100xx), which i a set the result should be (2331,2332,10011,10012), While i also want to give an additional condition which the id want to return both in investor and borrower was using gmail email address and phone number i.e 0811xx,0812xx,0813xx.
the following still returns wrong result and also contains id where iam not intended to related to the additional where condition, while still not join to the borrower_id.
SELECT
users.id, users.name
FROM
users
WHERE
users.id NOT IN (SELECT transactions.investor_id FROM transactions)
AND email LIKE '%#gmail%'
AND phone LIKE '0811%' OR phone LIKE '0812%' OR phone LIKE '0813%'

Your problem is the lack of parentheses around the or clauses.
But, you can simplify your query. Most databases support some form of regular expressions. If so, you can simplify the query to:
SELECT u.id, u.name
FROM users u
WHERE u.id NOT IN (SELECT t.investor_id FROM transactions t) AND
u.email LIKE '%#gmail%' AND
u.phone ~ '^081[123]';
The above happens to be Postgres syntax, but there is similar functionality in most databases.
I should point out that SQL Server does this with like:
SELECT u.id, u.name
FROM users u
WHERE u.id NOT IN (SELECT t.investor_id FROM transactions t) AND
u.email LIKE '%#gmail%' AND
u.phone LIKE '081[123]%';
Or you can even do:
SELECT u.id, u.name
FROM users u
WHERE u.id NOT IN (SELECT t.investor_id FROM transactions t) AND
u.email LIKE '%#gmail%' AND
LEFT(u.phone, 4) IN ('0811', '0812', '0813');

You are almost there. Put the OR conditions in brackets...
SELECT users.id,
users.name
FROM users
WHERE users.id NOT IN (
SELECT transactions.investor_id
FROM transactions
)
AND email LIKE '%#gmail%'
AND (
phone LIKE '0811%'
OR phone LIKE '0812%'
OR phone LIKE '0813%'
)

Related

SQL count how much field from record is showed in other table

I have two tables, the first one is USERS and the second one is TAGS.
this is the USERS table fields:
ID
NAME
and this is the TAGS table fields:
PICTURE_ID
USER_ID
now I want to count how much times one of the users is "taged" in the TAGS table (both based on the user_id but I want to be able to check according to the name).
example:
if I have the user
ID=1 NAME="aba"
and in the TAGS I have
PICTURE_ID=8 USER_ID=1,
PICTURE_ID=3 USER_ID=1.
so the number of times "aba" is taged in pictures is 2.
You could use a simple correlated aggregation here -
select u.Name, coalesce((select count(*) from Tags t where t.User_Id = u.Id),0) Tags
from Users u
where u.Id = 'aba';
SELECT COUNT(T.PICTURE_ID) AS TAGs_Count, U.NAME
FROM TAGS T
LEFT JOIN USERS U
ON U.ID = T.USER_ID
GROUP BY T.USER_ID, U.NAME
In case if you want to display counts just for specific User (here it's Aba)
SELECT COUNT(T.PICTURE_ID) AS TAGs_Count, U.NAME
FROM TAGS T
LEFT JOIN USERS U
ON U.ID = T.USER_ID
WHERE U.NAME LIKE 'Aba'
GROUP BY T.USER_ID, U.NAME
Or you can use wildcards if you don't know exact names you searching for:
WHERE U.NAME LIKE '%ba'
or
WHERE U.NAME LIKE 'Ab%'
or for both ends:
WHERE U.NAME LIKE '%b%'
If you want to have search case insensitive you use this:
WHERE UPPER(U.NAME) LIKE UPPER('Aba')
Also consider what operator actually you want to use.
LIKE and Equals ( = ) are not exactly the same.
More about that you'll find here

How to write the correct SQL query to find the most duplicate user?

That's my database design.
I need to find the person with the most albums using SQLite.
I tried this:
SELECT USERS.NAME, COUNT(USERS.NAME) AS 'value_occurrence' FROM USERS
INNER JOIN ALBUMS
ON USERS.ID = ALBUMS.USER_ID
GROUP BY USERS.NAME
ORDER BY 'value_occurrence'
DESC LIMIT 1;
but it didn't work and gave me the wrong result. Please help me find the right way to do this.
The logic is correct, but you may be getting tripped up by incorrect use of single quotes for aliases. Try this version:
SELECT u.NAME, COUNT(u.NAME) AS value_occurrence
FROM USERS u
INNER JOIN ALBUMS a ON a.USER_ID = u.ID
GROUP BY u.NAME
ORDER BY value_occurrence DESC
LIMIT 1;
The problem with ORDER BY 'value_occurrence' is that you are telling SQLite to order by a constant value. That is, every record in the result set will have the same value for ordering, which basically means that SQLite is free to choose any record as being the "first."
Note: As the answer by #Cazzym mentioned, you should be aggregating by the user ID, in case two or more users might have the same name.
The code basically looks fine, but it will return unexpected results where two users have the same name. That's why we have ID columns!
Try
SELECT USERS.NAME, COUNT(USERS.ID) AS 'value_occurrence' FROM USERS
INNER JOIN ALBUMS
ON USERS.ID = ALBUMS.USER_ID
GROUP BY USERS.ID, USERS.NAME
ORDER BY 'value_occurrence'
DESC LIMIT 1;
We can use group by Users.Id, Users.Name because each ID is going to only have one name associated with it, so it's still going to only create a single group per ID.

SQL query to find out the number of tickets

I have two tables in MS Access.
Table 1: users
ID (auto int)
Name
Table 2: tickets
ID (auto int)
userName (int) (refers to ID in users table)
How can I list the user names and the number of tickets submitted?
This should give you the results that you want. You will want to use an aggregate function COUNT() and a GROUP BY
SELECT u.name, count(t.username) TicketsSubmitted
FROM Users u
INNER JOIN tickets t
ON u.id = t.username
GROUP BY u.name
Count the tickets per user in a subquery, then list all the info per user.
SELECT u.Name AS UserName, t.ticketCount AS TicketsSubmitted
FROM users AS u
INNER JOIN ( SELECT COUNT(ID), userName AS ticketCount FROM tickets GROUP BY userName ) AS t
ON u.ID = t.userName
Should do it.
A make table query should allow you to query those two tables and create a third with the data you want.
The following link from the Microsoft Office website should give you the information you need.
http://office.microsoft.com/en-us/access-help/create-a-make-table-query-HA010108505.aspx
The two answers above give solid advice for the query to get the data you want.

How to make a nested query?

Have a table users and there is a field invited_by_id showing user id of the person who invited this user. Need to make a MySQL query returning rows with all the fields from users plus a invites_count field showing how many people were invited by each user.
Something like this:
SELECT
User.*, Count.count
FROM
users AS User,
(
SELECT COUNT(*) AS count FROM users WHERE users.invited_by_id=User.id
) AS Count;
This one is not working so I need a working one.
SELECT u.*,
(
SELECT COUNT(*)
FROM users ui
WHERE ui.invited_by_id = u.id
) AS cnt
FROM users u
Ok, first of all, count is a reserved word in sql so you can't use it as a table alias (unless you quote it in some way but don't do that). Secondly, the real way to solve this problem is to introduce a GROUP BY clause in your subquery.
Try this:
SELECT user3.*, subquery.theCount FROM
users AS user3
INNER JOIN (
SELECT
user1.id, count(user2.id) AS theCount
FROM
users AS user1
LEFT OUTER JOIN
users AS user2 ON user2.invited_by_id=user1.id
GROUP BY user1.id
) AS subquery ON subquery.id=user3.id;
Here is a dirty little secret about MySQL: It lets you cheat with the GROUP BY statement and select columns that are not in the GROUP BY list and also not in aggregate functions. Other RMDMSes don't let you do this.
SELECT
user1.*, count(user2.id) AS theCount
FROM
users AS user1
LEFT OUTER JOIN
users AS user2 ON user2.invited_by_id=user1.id
GROUP BY user1.id;

SQL Query without nested queries

Let's say we have these tables;
table user:
- id
- username
- email
table user2group:
- userid
- groupid
table group:
- id
- groupname
How do I make one query that returns all users, and the groups they belong to (as an array in the resultset or something..)
select u.id, u.username, u.email, g.groupid, g.groupname
from user u
join user2group ug on u.userid=ug.userid
join group g on g.groupid=ug.groupid
order by u.userid
As you are looping through the result set, each time you see a new userid make a new user object (or whatever) and add the groups to it.
Eric's answer is great, but I would use a LEFT JOIN instead of an INNER to get users that do not belong to any group as well.
SELECT
u.id,
u.username,
u.email,
g.groupid,
g.groupname
FROM
user u
LEFT JOIN user2group ug ON u.userid = ug.userid
LEFT JOIN group g ON g.groupid = ug.groupid
ORDER BY
u.userid
Both of the above are more or less correct (deepends if each user has a group or not). But they will also both give a result set with several entries for each user.
There are ways of concatenating every group member into one comma separated string, I'd suggest you read about it here:
http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/
Another method I personally like is to use bit values instead of the relational table user2group
table user then gets a int (or bigint) field group, and each group ID is assigned one bit value (ie: 1,2,4,8,16 and so on) The value of the user table's group field is then the sum of the groupID it's assigned to. To query if its got a group you do:
where (group AND groupID = groupID)