How to select records from multiple table
Table "users":
user_id|username|email|login|password
Table "users_log"
log_id|user_id|status|timestamp|message
Table "users_balance"
balance_id|user_id|status|amount
Table "users_roles"
role_id|status|role_name
Table "users_role"
role_id|user_id
how to retrieving all records by user email and log status and user role
Output:
log-timestamp|user_id|Username|email|role_name|balance-amount|log-message
Something like this I'm guessing.
SELECT
log.timestamp AS log_timestamp,
u.user_id,
u.username AS user_name,
u.email AS user_email,
role.name AS role_name,
bal.amount AS balance_amount,
log.message AS log_message
FROM users AS u
JOIN users_role AS ur ON ur.user_id = u.user_id
JOIN users_roles AS role ON role.role_id = ur.role_id
JOIN users_log AS log ON u.user_id = log.user_id
LEFT JOIN users_balance AS bal ON bal.user_id = u.user_id
WHERE u.email = #UserEmail
AND role.role_name = #RoleName
AND log.status = #LogStatus
And then set or replace the #UserEmail, #RoleName, #LogStatus variables by what you're looking for.
But depending on the data you might want to add a GROUP BY and an aggregate function like MAX or SUM, and perhaps extra criteria in the WHERE or HAVING clause.
You can use JOIN query to get data from multiple tables
Please try this,
SELECT usr.*,usrlg.*,usrbl.*,usrrl.*,usrrls.* FROM users AS usr JOIN users_log AS usrlg ON(usrlg.user_id=usr.user_id) JOIN users_balance AS usrbl ON (usrbl.user_id=usr.user_id)
JOIN users_role AS usrrl ON(usrrl.user_id=usr.user_id) JOIN users_roles AS usrrls ON(usrrls.role_id=usrrl.role_id)
WHERE usr.email='value' AND usrlg.status='value' AND usrrls.role_name='value'
You can do it through joins. Can refer below links.
https://www.guru99.com/joins.html
http://www.mysqltutorial.org/mysql-join/
https://www.tutorialspoint.com/mysql/mysql-using-joins.htm
Related
I'm having issues finding an appropriate NOT EXISTS-Query to replace my NOT IN one. I have to replace it because of the nullable-columns problem. However I'm rather new to SQL, so I can't get the right relations.
What I'm trying to do is to exclude all users that are already assigned to a practice, which do not have the "informal" flag set (in other words: Unassigned users with the informal flag). My current query is
SELECT USERS.UserID, USERS.Name
FROM USERS
WHERE USERS.Informal = true AND USERS.UserID NOT IN (
SELECT USERS.UserID
FROM PRACTICES
LEFT JOIN ATTENDS ON PRACTICES.PracticeID = ATTENDS.PracticeID
LEFT JOIN USERS ON ATTENDS.UserID = USERS.UserID
WHERE PRACTICES.PracticeID = 7
)
this is the relevant table structure for the query
I'd be very grateful if someoune could hint me in the right direction.
There is no ned to repeat the USERS table in the subquery -- for either NOT IN or NOT EXISTS. I strongly recommend NOT EXISTS (because it handles NULL values more intuitively):
SELECT u.UserID, u.Name
FROM USERS u
WHERE u.Informal = true AND
NOT EXISTS (SELECT USERS.UserID
FROM PRACTICES p
ATTENDS a
ON p.PracticeID = a.PracticeID
WHERE a.UserID = u.UserID AND p.PracticeID = 7
)
Background, I have a cron job that queries keywords associated with posts, if that keyword is found, a user is emailed about the post.
The cron job runs every minute so once a user has been emailed that notification should not happen again.
The following query runs:
SELECT DISTINCT p.id AS post_id, u.display_name, u.id AS user_id, u.email, k.keyword, k.id AS keyword_id
FROM posts p, user_subscriptions us, keywords_users ku, keywords k, users u
LEFT JOIN keyword_subscription_sent kss ON kss.user_id = u.id
LEFT JOIN keywords_posts kp ON kss.post_id = kp.post_id
WHERE us.keywords = 1
AND ku.user_id = u.id
AND ku.keyword_id = k.id
AND kp.keyword_id = k.id
#AND kss.user_id IS NULL AND kss.post_id IS NULL
LIMIT 0, 200
The query works as expected when the table keywords_posts kp is populated.
If the table keywords_posts kp is empty the query will never return anything.
I attempted to fix this by adding to the WHERE clause:
AND kss.user_id IS NULL AND kss.post_id IS NULL
But adding this to the WHERE clause will cause the query to never return anything at all at any time.
The desired result is:
The query will return all rows except listed in the keywords_posts kp table.
Suggestions:
Relocate the conditions that require a column to be non-NULL from the WHERE clause up to the appropriate ON clause of the outer join.
Don't mix the old-school comma syntax (for the join operation) with the JOIN keyword syntax. Ditch the comma syntax and just use JOIN. And move join conditions to the ON clause.
Moving the condition to the ON clause of the outer join will allow NULL values to be returned.
If we do it the WHERE clause, note that the condition
WHERE ( col = some_non_null_val AND col IS NULL )
is guaranteed to never evaluate to TRUE. (The condition is checked for each individual row.) Only rows where the condition evaluate to TRUE will be returned. Likely you meant to use OR in place of AND.
But we can avoid that OR if we just relocate the condition
col = some_non_null_val
to the ON clause of the outer join.
I hesitate to provide an example query as a demonstration. The original query is producing a semi-Cartesian product; for example what appears to be a cross join between users and user_subscriptions... the only criteria for matching to user_subscriptions is keywords=1. So I'm not understanding the specification.
OP reports that query is returning a correct result, but I'm suspicious that the query doesn't actually satisfy the intended specification. I suspect that the matching between users and user_subscriptions should include some additional criteria.
Without a more precise specification, including sample data and an example of expected output, I cannot in good conscience provide example SQL for OP use-case.
i think kp_keyword_id=k.id from your WHERE condition cause the query to return nothing where kp is empty,try to put that in JOIN instead so it become like this
SELECT DISTINCT p.id AS post_id, u.display_name, u.id AS user_id, u.email, k.keyword, k.id AS keyword_id
FROM posts p, user_subscriptions us, keywords_users ku, keywords k, users u
LEFT JOIN keyword_subscription_sent kss ON kss.user_id = u.id
LEFT JOIN keywords_posts kp ON kss.post_id = kp.post_id AND kp.keyword_id = k.id
WHERE us.keywords = 1
AND ku.user_id = u.id
AND ku.keyword_id = k.id
LIMIT 0, 200
Hello vveryone and thanks for you input.
The following worked:
SELECT * FROM (SELECT u.id as user_id, u.email, u.display_name, k.id as keyword_id, k.keyword, p.id AS post_id, kp.post_id AS kp_post_id, kp.keyword_id AS kp_keyword_id,
ku.user_id AS ku_user_id, ku.keyword_id AS ku_keyword_id
FROM users u, keywords k, posts p, keywords_posts kp, user_subscriptions us, keywords_users ku
WHERE kp.post_id = p.id AND us.keywords = 1 AND kp.keyword_id = k.id AND ku.keyword_id = k.id AND u.id = ku.user_id
GROUP BY kp.post_id, u.id) AS ukp LEFT JOIN keyword_subscription_sent kss ON ukp.user_id = kss.user_id AND kss.post_id = ukp.post_id WHERE kss.post_id IS NULL
I'm trying to export af list of subscribers from a database, and while my sql call works, it's missing some logic. My problem is - I want to export users with an expired membership. Some users might have both an expired membership and an active one. I don't want those users on my list.
I'm thinking I need a subquery to filter users with both an expired and an active membership, but I'm not sure how.
Here's my current query:
SELECT
jos_users.name,
jos_users.email,
jos_users.username,
jos_payplans_subscription.expiration_date,
jos_payplans_subscription.status,
jos_payplans_subscription.total,
jos_payplans_subscription.subscription_id
FROM jos_payplans_subscription
LEFT JOIN jos_users ON jos_payplans_subscription.user_id = jos_users.id
LEFT JOIN jos_payplans_user ON jos_payplans_user.user_id = jos_users.id
WHERE (jos_payplans_subscription.expiration_date BETWEEN '2015-09-01 00:00:00' AND '2015-10-31 00:00:00')
I'll appreciate any help.
Thanks :-)
You could join back to the subscriptions table to find the active subs, and ignore those:
select q.name, q.email, q.username, q.expiration_date, q.status, q.total, q.subscription_id
from (
SELECT
jos_users.name,
jos_users.email,
jos_users.username,
jos_payplans_subscription.expiration_date,
jos_payplans_subscription.status,
jos_payplans_subscription.total,
jos_payplans_subscription.subscription_id
FROM jos_payplans_subscription
LEFT JOIN jos_users ON jos_payplans_subscription.user_id = jos_users.id
LEFT JOIN jos_payplans_user ON jos_payplans_user.user_id = jos_users.id
WHERE (jos_payplans_subscription.expiration_date BETWEEN '2015-09-01 00:00:00' AND '2015-10-31 00:00:00')
) q
join jos_payplans_subscription s on s.user_id = q.user_id
group by q.name, q.email, q.username, q.expiration_date, q.status, q.total, q.subscription_id
having min(s.expiration_date) is not null;
Edit: Forgot the is
having min(s.expiration_date) not null
to
having min(s.expiration_date) is not null
A similar thing I've done before was create a junction table between a users and membership table called "activeMembership." This had a composite PK of userID and membershipID and a column called "membershipSatus"
Then you could easily do:
SELECT username, email, membershipType, membershipStatus FROM
activeMembership
JOIN users on users.userID = activeMembership.userID
JOIN membership ON membership.membershipID = activeMembership.membershipID
WHERE membershipStatus='Inactive';
Maybe altering the schema and creating a many to many relationship would solve your problem?
I have three tables in my MySql database :
Vehicle
Id_vehicle_pk( int,auto-increment,pk)
id_driver_fk(varchar,fk, nullable)
User
Id_user_pk(varchar,pk)
mail(varchar)
Collaborator
Id_coll_pk(int,pk)
Id_user_fk(varchar,fk)
First_Name(varchar)
Last_Name(varchar)
I'd like to create a view which join these three tables, so i try this
select Id_vehicle_pk, id_driver_fk,mail, Id_coll_pk, First_Name,Last_Name
from
Vehicle join User join
Collaborator
where
`Vehicle`.`id_driver_fk` = `User`.`Id_user_pk`
and `Collaborator`.`Id_user_fk` = `User`.`Id_user_pk`
group by Id_vehicle_pk
Having Id_vehicle_pk> 0
But I have wrong result caused by null values of id_driver_fk. So I need to know :
How can I fix my query?
I think you are looking for the LEFT JOIN clause which allows to get all records from the main table even if there are no foreign key matches to other tables:
SELECT
v.Id_vehicle_pk,
v.id_driver_fk,
u.mail,
c.Id_coll_pk,
c.First_Name,
c.Last_Name
FROM Vehicle v LEFT JOIN
User u ON v.id_driver_fk = u.Id_user_pk LEFT JOIN
Collaborator c ON c.Id_user_fk = u.Id_user_pk
WHERE Id_vehicle_pk> 0
Also it is a best practice to put join condition inside the join rather than WHERE clause.
You are missing the on clause in both of your joins.
select Id_vehicle_pk,
id_driver_fk,
mail, Id_coll_pk,
First_Name,
Last_Name
from Vehicle
join User on id_driver_fk = Id_user_pk
join Collaborator on Id_user_pk = Id_user_fk
group by Id_vehicle_pk
Having Id_vehicle_pk> 0
I have a litte problem with a mysql query.
I use 5 tables:
user_has_data (uid, dataid); users (uid, uname); user_in_group(uid, groupid, data); groups(groupid, data, packageid); packages(packageid, name)
all ids are PK. I want to build a sql query that finds a user, which belongs to a specified dataid, by its uname and checks if the user is in a group (relation in table user_in_group) belonging to a specified package (a group is assigned to one package). if so data from users, package and group should be fetched, otherwise only the user data should be fetched. Therefore I use left joins, so I can also get the users with no group:
SELECT `uac`.`uid`, `u`.`uid`, `uig`.`groupid`, `ag`.`packageid`
FROM `user_has_data` AS `uac`
INNER JOIN `users` AS `u` ON u.uid = uac.uid
LEFT JOIN `user_in_group` AS `uig` ON uig.uid = uac.uid
LEFT JOIN `groups` AS `ag` ON (ag.groupid = uig.groupid) AND (ag.packageid = 2)
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
GROUP BY `u`.`uid`
Unfortunately I get wrong results: I get groups that have a different packageid than stated in the join, if the user has another group assigned to him with a different packageid.
probably this is because the first left join has no restrictions to packageid and the second is a left join and so it has no restrictions on the result (packageid is NULL for all results, but should have values). If I change the second left join to a ordinary join, the group problem would be fixed but the query cant find users without group any more.
Any ideas how to fix this or even possible?
thanks in advance!
Are you saying that you are actually seeing the value ag.packageid = 2 in your query results?
If not, I think you might try something like:
SELECT `uac`.`uid`, `u`.`uid`, `g`.`groupid`, `g`.`packageid`
FROM `user_has_data` AS `uac`
INNER JOIN `users` AS `u` ON u.uid = uac.uid
LEFT JOIN (`user_in_group` AS `uig`
INNER JOIN `groups` AS `ag` ON (ag.groupid = uig.groupid) AND (ag.packageid = 2) )
AS `g` ON uac.uid = g.uid
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
GROUP BY `u`.`uid`
Because you are limiting your search to a specific group packageid of '2', why not just make both of your LEFT JOIN INNER JOINS and then throw in ag.packageid = 2 in your WHERE clause?
SELECT `uac`.`uid`, `u`.`uid`, `uig`.`groupid`, `ag`.`packageid`
FROM `user_has_data` AS `uac`
INNER JOIN `users` AS `u` ON u.uid = uac.uid
LEFT OUTER JOIN `user_in_group` AS `uig` ON uig.uid = uac.uid
LEFT OUTER JOIN `groups` AS `ag` ON ag.groupid = uig.groupid
WHERE (uac.dataid = '3') AND (u.uname LIKE 'test%')
AND (ag.packageid = 2 OR uig.uid IS NULL)
GROUP BY `u`.`uid`
I know LEFT JOIN and LEFT OUTER JOIN mean the same thing, but I like to be explicit. With the condition in your join, I bet you were getting groups with different packages, but weren't getting the packages?