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
Related
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.
I have a table of ratings for comments, when I fetch comments, I also fetch the ratings and I also want to be able to display which comments the logged user has already voted on. This is what I am doing now
SELECT
c.id,
c.text,
c.datetime,
c.author,
u.email AS author_name,
SUM(cr.vote) AS rating,
cr2.vote AS voted
FROM comments c
LEFT JOIN users u ON u.id = c.author
LEFT JOIN comments_ratings cr ON c.id = cr.comment
LEFT JOIN comments_ratings cr2 ON c.id = cr2.comment AND cr2.user = :logged_user_id
GROUP BY c.id ORDER BY c.id DESC
But I don't like how I'm performing a second join on the same table. I know it is perfectly valid but if I could get the information I want from the first join, which is there anyway, why perform a second one?
Is it possible to figure out if a row with column user equal to :logged_user_id exists on table comments_ratings cr before executing the aggregate function(s)?
P.S.: If someone could come up with a better title, people can find in future, I'd also appreciate that.
You can do what you want with conditional aggregation:
SELECT c.id, c.text, c.datetime, c.author, u.email AS author_name,
SUM(cr.vote) AS rating,
MAX(cr.user = :logged_user_id) as voted
FROM comments c LEFT JOIN
users u
ON u.id = c.author LEFT JOIN
comments_ratings cr
ON c.id = cr.comment
GROUP BY c.id
ORDER BY c.id DESC;
the MYSQL query below combines a number of tables. However, as you can see, I would like to add a LEFT JOIN at the end on the receipt table. The query returns an error when I add the LEFT JOIN. Anybody know the best way to LEFT JOIN the receipt table to the rest of the query. Sorry if this is a newbie question. Thanks !!
SELECT user_name, expense_category, merchant_name, expense_cost, expense_date, expense_status, receipt_image, expense_comment
FROM users, expenses, merchants, receipts
WHERE ".$adminId." = expenses.admin_id
AND expenses.user_id = users.user_id
AND expenses.merchant_id = merchants.merchant_id
AND LEFT JOIN (receipts)
ON expenses.receipt_id = receipts.receipt_id
Here is a clean approach of doing it, note that I have added alias for the tables for better readability so you may use the alias name in the select statement to fetch the column from the proper table.
SELECT
u.user_name,
ex.expense_category,
mer.merchant_name,
ex.expense_cost,
ex.expense_date,
ex.expense_status,
re.receipt_image,
ex.expense_comment
FROM users u
JOIN expenses ex on ex.user_id = u.user_id
JOIN merchants mer on mer.merchant_id = ex.merchant_id
LEFT JOIN receipts re on re.receipt_id = ex.receipt_id
where
ex.admin_id = '$adminId'
Try this,
SELECT user_name, expense_category, merchant_name, expense_cost, expense_date, expense_status, receipt_image, expense_comment
FROM users, expenses, merchants, receipts
LEFT JOIN receipts ON expenses.receipt_id = receipts.receipt_id
WHERE ".$adminId." = expenses.admin_id
AND expenses.user_id = users.user_id
AND expenses.merchant_id = merchants.merchant_id
Use join clauses instead of where clause. I.e.
SELECT user_name, expense_category, merchant_name, expense_cost, expense_date, expense_status, receipt_image, expense_comment
FROM users
INNER JOIN expenses on users.user_id = expenses.expenses_id
INNER JOIN merchants on merchants.merchant_id = expenses.merchant_id
LEFT JOIN (receipts)
ON expenses.receipt_id = receipts.receipt_id
WHERE ".$adminId." = expenses.admin_id
Note that any columns from the receipts will be NULL in the select statement whenever there's no matching record.
Suppose we have this model:
As you see industry_id can be null. Can I fetch industry.name (if any), user.description, profile.name and project.title (all project titles) he/she has with a single MySQL query while having user.id?
Yes, JOIN the two tables:
SELECT
i.name,
u.id
FROM Industry AS i
LEFT JOIN `User` AS u ON u.industry_id = i.industry_id;
Update:
For multiple tables:
SELECT
i.Name AS InustryName,
p.Name AS UserName,
u.Description,
j.title AS ProjectTitle
FROM Industry AS i
INNER JOIN User AS u ON i.id = u.id
INNER JOIN Profile AS p ON p.user_id = u.id
INNER JOIN Project AS j ON u.id = j.user_id;
Note that: I used INNER JOIN between the tables, this will give you only the matched rows from the joined tables, you might need to use LEFT JOIN instead of innner join to include the untmatched rows, i.e., to get those industries that has no entries in the other tables. See this blog post:
A Visual Explanation of SQL Joins
I have been trying to join two tables (USERS AND USERS_ROLES) based on their role id I put the left join on following query
users.id = users_roles.fk_user_id
but the output is not correct of users_roles.fk_role_id coulmun and shows NULL where it should display the id of users.id = users_roles.fk_user_id that is 4 (at most places) because on users.id = users_roles.fk_user_id the value of users_roles.fk_role_id = 4
Kindly let me know how can i fix that so my query should result the exact vlaues of ids where they match,
Thanks
SELECT users.id, users.v_first_name, users.v_last_name, user_facility.fk_facility_id,users.fk_tenant_id, marital_status.v_marital_status,
users.v_blood_type, NOW(),users_roles.fk_role_id
FROM users
LEFT JOIN (user_facility, marital_status, users_roles) ON
users.id = user_facility.fk_user_id AND users.fk_marital_status_id=marital_status.id AND users.id = users_roles.fk_user_id
Usage of AND operator when used with Left or Right join gives different result. You should be clear what you are trying to accomplish..See this
well it is what you get by first implicitly inner-joining 3 tables and then explicitly left-joining the result to a 4th table only if 3 conditions relevant to all of the 3 inner-joinded tables are matched (i.e. when 3rd condition is false, nothing is joined from either of the 2 remaining tables)
i strongly suggest not to combine implicit and explicit joins, i personally use explicit joins all the time:
if you need an outer join:
SELECT ...
FROM users
LEFT JOIN user_facility ON users.id = user_facility.fk_user_id
LEFT JOIN marital_status ON users.fk_marital_status_id=marital_status.id
LEFT JOIN users_roles ON users.id = users_roles.fk_user_id
if you need an inner join:
SELECT ...
FROM users
JOIN user_facility ON users.id = user_facility.fk_user_id
JOIN marital_status ON users.fk_marital_status_id=marital_status.id
JOIN users_roles ON users.id = users_roles.fk_user_id
or if you prefere implicit inner joins for some obscure reason:
SELECT ...
FROM users,
user_facility,
marital_status,
users_roles
WHERE users.id = user_facility.fk_user_id
AND users.fk_marital_status_id=marital_status.id
AND users.id = users_roles.fk_user_id
(implicit outer joins are getting deprecated in all RDBMS as far as i know)
When it shows NULL it means there isn't a correspondency (relation) between all tables in the JOIN clause.
If you want to show only the ones that have relations in all tables, use INNER JOIN instead.
SELECT u.id,
u.v_first_name,
u.v_last_name,
uf.fk_facility_id,
u.fk_tenant_id,
ms.v_marital_status,
u.v_blood_type,
NOW(),
ur.fk_role_id
FROM users u
INNER JOIN user_facility uf ON u.id = uf.fk_user_id
INNER JOIN marital_status ms ON u.fk_marital_status_id=ms.id
INNER JOIN users_roles ur ON u.id = ur.fk_user_id