How to get good results from DB - mysql

i have a problem with sql query.
I need to get list of users. The problem is the left join i use.
this is my query
SELECT
u.*
FROM
users u LEFT JOIN game g on g.user_id = u.user_id
LEFT JOIN game_actions ga on ga.game_id = g.id
LEFT JOIN emails e on e.id = ga.email_id
WHERE
u.user_id = 0
AND u.is_contact_by_email = 1
AND email.type = 2
this query returns the same user more then once because of the join with other tables
i want this query to return each user just one time.
i'm using sql developer.
thanks in advanced.

Given that you're not using game, game_actions, or emails for any purpose (they're not filtering users, and you're not enriching the results with data from either of these tables), there's no need to join those tables at all:
SELECT
u.*
FROM users u
WHERE u.user_id = 0
AND u.is_contact_by_email = 1

You may group result by user_id and use aggregate functions to return other fields, for eaxmple -
SELECT u.user_id, GROUP_CONCAT(g.game_id) games FROM users u
LEFT JOIN game g
ON g.user_id = u.user_id
LEFT JOIN game_actions ga
ON ga.game_id = g.id
LEFT JOIN emails e
ON e.id = ga.email_id
WHERE
u.user_id = 0 AND u.is_contact_by_email = 1
GROUP BY
u.user_id

I suppose there are more games, actions, and emails for each user. How do you imagine the result table to look like? Because when you are selecting only from user table (SELECT u.*), then there is no point in joining others. If you need the other tables, use GROUP BY (u.user_id) to group rows by user.

Try to use keyword distinct with your query

Related

Making a query with several JOINS

I am stuck with some SQL query.
I have four tables. Which are connected:
user =>user_account=>acount_profile_entries=>profile_entries
From left to right they are one to many.
user_account has a user_id field as FK.
account_profile_field has user_account_id and profile_entry_id.
Profile_entries has a text field that I need to show for each user (account).
I need to write a query that will show me, all accounts for every user, and its profile entries.
I am sorry if this is confusing, I tried to make it simple
This is what I have done so far. I can show all accounts for every user and this is the point I am stuck with. Last two commented out Joins are not working properly. I believe I am close somewhat, I just need a push :)
SELECT
u.email AS Email,
u.id AS UserId,
ua.id AS UserAccountId,
ua.app_id AS Application
FROM users AS u
INNER JOIN user_accounts ua ON ua.user_id = u.id
-- INNER JOIN account_profile_entries ape ON ape.user_account_id = ua.id
-- INNER JOIN profile_entries as pe ON pe.id = ape.profile_entry_id
limit 10
Try this SQL Query with using LEFT JOIN
Description :- The MySQL LEFT JOIN joins two tables and fetches rows based on a condition, which is matching in both the tables and the unmatched rows will also be available from the table written before the JOIN clause.
SYNTAX
SELECT column_name(s)
FROM table1
LEFT JOIN table2 ON table1.column_name = table2.column_name;
SELECT u.*,
u.id AS UserId,
ua.id AS UserAccountId,
ua.app_id AS Application,pe.* FROM `users` u
LEFT JOIN user_accounts ua ON ua.user_id = u.id
LEFT JOIN account_profile_entries ape ON ape.user_account_id = ua.id
LEFT JOIN profile_entries as pe ON pe.id = ape.profile_entry_id LIMIT 10

MySQL: Find users with no submission

I'm struggling a little bit with a query and hope you can help.
I have two tables. On with all the users and one with information from submitted forms.
Both contain the user ID.
What I would need to find out is which user from the users table does not appear on the report table.
This is what I have so far:
SELECT u.ID, u.display_name, u.user_email, r.user_id
FROM users AS u
LEFT JOIN report AS r ON u.ID = r.user_id
WHERE NOT EXISTS(
SELECT *
FROM report AS rr
WHERE u.ID = rr.user_id
)
This seems to be fine for the users who absolutely have never submitted the form.
But the reports table also contains a date column and I was wondering how I can get this grouped by day.
In the front end then I will hopefully have a table which shows:
date: user:
2015-01-01 user a
2015-01-01 user f
2015-01-02 user g
2015-01-02 user a
2015-01-03 user z
2015-01-03 user x
Where the users are those who have not submitted the form that day.
Hope you can help. Thank in advance!
If you want to get a list of users that doesn't have any rows in the report table then you can generate a set that is the Cartesian product of the users and the dates that are present in the report table, and then do a left join with that set and check for null.
The Cartesian set formed by the cross join will contain all possible combinations of dates and users; that is would the report table would contain is all users had added reports on all available dates.
select r.date, u.user_id
from report r
cross join users u
left join (select r.date, r.user_id from users as u join report as r on u.id = r.user_id)
a on a.date = r.date and a.user_id = u.user_id
where a.date is null
Sample SQL Fiddle
With most other databases this could have been done with a set difference operator (minus or except) instead of a left join.
I'm making assumptions about column names in your report table for this answer:
SELECT x.report_date, u.user_id, u.display_name
FROM users u
JOIN (
SELECT DISTINCT report_date
FROM reports
) x
LEFT JOIN reports r
ON r.user_id = u.user_id
AND r.report_date = x.report_date
WHERE r.report_date IS NULL
ORDER BY x.report_date, u.user_id
Check out this fiddle: http://sqlfiddle.com/#!9/407ac/5
Left outer join with where clause...
Here is a good link ...
http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
SELECT * FROM `users`
LEFT OUTER JOIN `report`
ON `users`.`ID` = `report`.`user_id`
WHERE `report`.`user_id` IS null
ORDER BY `report`.`Date`
Surely you could just pass in the date you wanted to check?
so something like this (using #reportDate as the parameter):
SELECT * FROM users
LEFT OUTER JOIN report
ON users.ID = report.user_id
WHERE report.user_id IS NULL
AND report.Date = #reportDate
You can get the pairs of users/dates without reports. Generate all possible rows using a cross join and then filter out the ones that exist:
select u.*, r.date
from users u cross join
(select distinct date from reports r) d left join
reports r
on u.id = r.user_id and d.date = r.date
where r.userid is null;

LEFT JOIN 2 INNER JOIN Tables Without Subquery

I have 3 Tables: Jobs, Users, Applications.
I'd like a list of all jobs and optionally "any" applications submitted per each job but only if I have data for the user who submitted the application.
I vaguely remember seeing some obscure syntax in which 2 tables are joined to a query as if being a single table, something like:
select j.title, a.id, u.name from jobs j
left join applications a join users u on a.job_id=j.id and a.user_id = u.id
I know I could accomplish this with a subquery, but does a syntax of this nature exist?
Update
The answers I've received so far assume I want only a basic join. Though they break the intended logic posed in the question. Perhaps I've should've posted the subquery equivalent to illustrate the type of query I'd like to run.
select j.job_id, au.application_id, au.user_id from jobs j
left join (
select a.job_id, u.user_id from applications a
join users u on u.user_id = a.user_id
) au on j.job_id = au.job_id
You need both of these to be outer joins if you chain them the "simple" way:
select *
from jobs j
left outer join application a on a.job_id = j.id
left outer join users u on u.user_id = a.id
Since I take it that an application requires a user you can force the inner join to happen first in this way. Maybe that's the syntax question you were asking about. The parens are generally optional in my experience but I don't know a lot of MySQL:
select *
from jobs j
left outer join (application a
inner join users u on a.user_id = u.id) on a.job_id = j.id
This is where a right join comes up sometimes so the query can be written from top to bottom without any nesting:
select *
from application a
inner join users u on u.user_id = a.id on
right outer join jobs j on a.job_id = j.id
You were almost there, your only mistake was to put the both join conditions after the second join.
select *
from jobs j
left join application a on on.job_id = j.id
left join users u on u.user_id = u.id
Note that the maximum number of tables that can be referenced in a join is 61 (in MySQL and probably most of the popular DBMS).
See documentation.

MySql database selecting count(column) using inner joins

I have three tables
USER : idUser, Username
USERLOCATION : idUser, idLocation
SESSION : idUser, idSession
What I want to find is all the users that are from a particular location and count how many sessions they have had. I'm nearly there with this SQL
SELECT u.idUser, u.Username, s.idSession
FROM rempad.User u
INNER JOIN rempad.UserLocation l ON u.idUser = l.idUser
INNER JOIN rempad.Session s ON u.idUser = s.idUser
WHERE l.idLocation = 12
This returns all the users belonging to a particular location and all the session ids. Where I am stuck is that I really want to be able able to count the the sessions for each user.
I've tried...
SELECT u.idUser, u.Username, COUNT(s.idSession) as SessionCount
but this returns only a single row and counts all the sessions in the session table rather than counting the sessions that belong to each individual user at that location.
Do I need to do a nested SELECT statement? I'm not really sure how to go about writing the query.
Any help much appreciated.
L
Try this:-
SELECT u.idUser, u.Username, count(s.idSession) as x
FROM rempad.User u
INNER JOIN rempad.UserLocation l ON u.idUser = l.idUser
INNER JOIN rempad.Session s ON u.idUser = s.idUser
WHERE l.idLocation = 12
GROUP BY u.iduser,
u.username
I believe it would be better to use Group by along with the above
SELECT u.iduser,
u.username,
Count(s.idsession) AS x
FROM USER u
INNER JOIN userlocation l
ON u.iduser = l.iduser
INNER JOIN session s
ON u.iduser = s.iduser
WHERE l.idlocation = 12
GROUP BY u.iduser,
u.username

Select Two Values Based Off Same Column

I am trying to select two usernames in one row of a query one would be called 'username' and the second one say 'username2'. This is the code I have atm. The users table uses a primary key of user_id.
SELECT
r.report_id,
r.poster_id,
r.reporter_id,
u.username,
(2nd username)
FROM reports r,
users u
WHERE r.report_id = :report_id
AND r.reporter_id = u.user_id
AND r.poster_id = u.user_id
you need to join the table user twice
SELECT
r.report_id,
r.poster_id,
r.reporter_id,
u.username AS ReporterName,
b.userName as PosterName
FROM
reports r
INNER JOIN users u
ON r.reporter_id=u.user_id
INNER JOIN users b
ON r.poster_id=b.user_id
WHERE
r.report_id=:report_id
Here is the code for MySQL
SELECT
r.report_id,
r.poster_id,
r.reporter_id,
u.username,
u.username username2,
FROM reports r,
users u
WHERE r.report_id = :report_id
AND r.reporter_id = u.user_id
AND r.poster_id = u.user_id