Is there a way with single mysql query to output all customers and all their orders including customers without orders? I have:
Customers:
╔════╦═════════════╗
║ ID ║ NAME ║
╠════╬═════════════╣
║ 1 ║ John Smith ║
║ 2 ║ Jim Jimmers ║
╚════╩═════════════╝
Orders:
╔═══════╦══════════╦═══════╗
║ id ║ ClientID ║ Status║
╠═══════╬══════════╬═══════╣
║ 1 ║ 1 ║ wait ║
║ 2 ║ 1 ║ rdy ║
╚═══════╩══════════╩═══════╝
How do I select a result like:
╔════╦═════════════╦═════════════╦═════════════╗
║ ID ║ NAME ║ Order Id ║ Order Status║
╠════╬═════════════╬═════════════╬═════════════╣
║ 1 ║ John Smith ║ 1 ║ wait ║
║ 1 ║ John Smith ║ 2 ║ rdy ║
║ 2 ║ Jim Jimmers ║ ║ ║
╚════╩═════════════╩═════════════╩═════════════╝
Just use a left join between the two tables:
SELECT c.ID, c.NAME, o.id AS OrderId, o.Status AS OrderStatus
FROM Customers c
LEFT JOIN Orders o
ON o.ClientID = c.ID
ORDER BY c.ID, o.id;
Related
The tables below are an example table structure.
The query I am trying to write is something like:
SELECT * FROM jobs LEFT JOIN assigned ON jobs.id = assigned.job_id;
However, as you can see the left join will product multiple matches in the case of job 100, but the above query will only return one match.
Is it possible to concatenate the results into a comma separated string for the left join?
If possible, a step further would be, is it possible to replace the assigned.user_id with the users.name column in the concatenated comma separated string.
users
╔═══╦════════════╦═════════════╗
║ ║ id ║ name ║
╠═══╬════════════╬═════════════╣
║ 1 ║ 1 ║ Matt ║
║ 2 ║ 2 ║ Phil ║
║ 3 ║ 3 ║ Chris ║
╚═══╩════════════╩═════════════╝
jobs
╔═══╦════════════╦═════════════╗
║ ║ id ║ name ║
╠═══╬════════════╬═════════════╣
║ 1 ║ 100 ║ Do this ║
║ 2 ║ 101 ║ Do that ║
║ 3 ║ 102 ║ And this ║
╚═══╩════════════╩═════════════╝
assigned
╔═══╦════════════╦═════════════╗
║ ║ user_id ║ job_id ║
╠═══╬════════════╬═════════════╣
║ 1 ║ 1 ║ 100 ║
║ 2 ║ 2 ║ 100 ║
║ 3 ║ 1 ║ 101 ║
╚═══╩════════════╩═════════════╝
SELECT jobs.id,
jobs.name,
GROUP_CONCAT( users.name order by users.name) as workersOnTheJob
FROM
jobs
LEFT JOIN assigned
ON jobs.id = assigned.job_id
LEFT JOIN users
on assigned.user_id = users.id
group by
jobs.id,
jobs.name
I have three tables named "users","user_hobbies" and "hobbies". Below is the sample tables with values;Below is the users table with fields id, name and age
╔════╦══════╦═════╗
║ ID ║ NAME ║ AGE ║
╠════╬══════╬═════╣
║ 1 ║ abc ║ 23 ║
║ 2 ║ xyz ║ 24 ║
║ 3 ║ pqr ║ 21 ║
╚════╩══════╩═════╝
and below is user_hobbies table with fields id, user_id and hobby_id
╔════╦═════════╦══════════╗
║ ID ║ USER_ID ║ HOBBY_ID ║
╠════╬═════════╬══════════╣
║ 1 ║ 1 ║ 1 ║
║ 2 ║ 1 ║ 2 ║
║ 3 ║ 1 ║ 3 ║
║ 4 ║ 2 ║ 4 ║
║ 5 ║ 2 ║ 3 ║
║ 6 ║ 2 ║ 5 ║
║ 7 ║ 3 ║ 2 ║
║ 8 ║ 4 ║ 6 ║
╚════╩═════════╩══════════╝
. Below is the hobbies table with fields id and desc
╔════╦═══════════╗
║ ID ║ DESC ║
╠════╬═══════════╣
║ 1 ║ music ║
║ 2 ║ chatting ║
║ 3 ║ cricket ║
║ 4 ║ badminton ║
║ 5 ║ chess ║
║ 6 ║ cooking ║
╚════╩═══════════╝
. The actual requirement is that i need a query to retrieve name, age, hobby_id and desc (see an example below)
╔══════╦═════╦══════════╦═════════════════════════╗
║ NAME ║ AGE ║ HOBBYID ║ DESC ║
╠══════╬═════╬══════════╬═════════════════════════╣
║ abc ║ 23 ║ 1,2,3 ║ music,chatting,cricket ║
║ pqr ║ 21 ║ 2 ║ chatting ║
║ xyz ║ 24 ║ 4,3,5 ║ badminton,cricket,chess ║
╚══════╩═════╩══════════╩═════════════════════════╝
You need to join the tables first and use an aggregate function called GROUP_CONCAT().
SELECT a.Name,
a.Age,
GROUP_CONCAT(c.ID) hobbyIDs,
GROUP_CONCAT(c.desc) descList
FROM users a
INNER JOIN user_hobbies b
ON a.ID = b.user_ID
INNER JOIN hobbies c
ON b.hobby_ID = c.ID
GROUP BY a.Name, a.Age
SQLFiddle Demo
MySQL GROUP_CONCAT()
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
OUTPUT
╔══════╦═════╦══════════╦═════════════════════════╗
║ NAME ║ AGE ║ HOBBYIDS ║ DESCLIST ║
╠══════╬═════╬══════════╬═════════════════════════╣
║ abc ║ 23 ║ 1,2,3 ║ music,chatting,cricket ║
║ pqr ║ 21 ║ 2 ║ chatting ║
║ xyz ║ 24 ║ 4,3,5 ║ badminton,cricket,chess ║
╚══════╩═════╩══════════╩═════════════════════════╝
I have two tables:
all_countries
╔════╦═════════════╗
║ ID ║ COUNTRY ║
╠════╬═════════════╣
║ 1 ║ USA ║
║ 2 ║ China ║
║ 3 ║ India ║
║ 4 ║ France ║
║ 5 ║ UK ║
║ 6 ║ Australia ║
║ 7 ║ Philippines ║
╚════╩═════════════╝
supported_countries
╔════════════╦═══════════╦═══════════╗
║ COUNTRY_ID ║ COUNTRY ║ FILTER_ID ║
╠════════════╬═══════════╬═══════════╣
║ 1 ║ USA ║ 1 ║
║ 2 ║ China ║ 1 ║
║ 3 ║ India ║ 1 ║
║ 4 ║ France ║ 2 ║
║ 1 ║ USA ║ 2 ║
║ 6 ║ Australia ║ 2 ║
╚════════════╩═══════════╩═══════════╝
Query:
SELECT a.*
FROM all_countries a
LEFT JOIN supported_countries s
ON a.id = s.country_id
WHERE s.country_id IS NULL;
So as per above example I should get.
UK
Philippines
It works fine, but what if, if I filter the country example I choose to filter = 2.
i get zero result.
SELECT a.*
FROM all_countries a
LEFT JOIN supported_countries s
ON a.id = s.country_id
WHERE s.filter = 2 AND s.country_id IS NULL;
supposed to be i want to get this result, if filter = 2.
╔════╦═════════════╗
║ ID ║ COUNTRY ║
╠════╬═════════════╣
║ 2 ║ China ║
║ 3 ║ India ║
║ 5 ║ UK ║
║ 7 ║ Philippines ║
╚════╩═════════════╝
Am I doing the correct query?
add the condition on the ON clause,
SELECT a.*
FROM all_countries a
LEFT JOIN supported_countries s
ON a.id = s.country_id AND
s.filter_ID = 2 -- <<=== HERE
WHERE s.country_id IS NULL;
SQLFiddle Demo
Result:
╔════╦═════════════╗
║ ID ║ COUNTRY ║
╠════╬═════════════╣
║ 2 ║ China ║
║ 3 ║ India ║
║ 5 ║ UK ║
║ 7 ║ Philippines ║
╚════╩═════════════╝
Here i have 2 tables user and userStore
user Table
╔════╦══════╦════════╦═══════════╗
║ ID ║ NAME ║ ROLE ║ STORECODE ║
╠════╬══════╬════════╬═══════════╣
║ 1 ║ A ║ Admin ║ ║
║ 2 ║ B ║ Store ║ 1 ║
║ 3 ║ C ║ Store ║ ║
║ 4 ║ D ║ Client ║ ║
║ 5 ║ E ║ Staff ║ ║
╚════╩══════╩════════╩═══════════╝
userStore Table
╔════╦══════════╗
║ ID ║ CATEGORY ║
╠════╬══════════╣
║ 1 ║ X ║
║ 2 ║ X ║
╚════╩══════════╝
Output
╔════╦══════╦════════╦═══════════╦══════════╗
║ ID ║ NAME ║ ROLE ║ STORECODE ║ CATEGORY ║
╠════╬══════╬════════╬═══════════╬══════════╣
║ 1 ║ A ║ Admin ║ ║ ║
║ 2 ║ B ║ Store ║ 1 ║ X ║
║ 4 ║ D ║ Client ║ ║ ║
║ 5 ║ E ║ Staff ║ ║ ║
╚════╩══════╩════════╩═══════════╩══════════╝
I want to fetch all the rows from user table with the role other than store. And wanted to include the store role only if it have match in the userstore table.
In the output you can see that the id=3 is not available since it doesn't have match from user store.
This should be straight forward, use LEFT JOIN
SELECT a.*, b.*
FROM user a
LEFT JOIN userStore b
ON a.StoreCode = b.ID
WHERE (a.role <> 'Store') OR
(a.role = 'Store' AND NOT b.ID IS NULL )
SQLFiddle Demo
Other Source
Visual Representation of Join
Try this:
SELECT u.id, u.name, u.role, u.StoreCode, IFNULL(us.id, '') id, IFNULL(us.Category, '') Category
FROM USER u
LEFT JOIN userStore us ON u.StoreCode = us.id
WHERE IF(LOWER(u.role) = 'store', u.StoreCode IS NOT NULL AND u.StoreCode != '', TRUE);
I have two table
The table structure goes something like this
Table A
╔══════╦════════╗
║ P_ID ║ P_NAME ║
╠══════╬════════╣
║ 1 ║ name1 ║
║ 2 ║ name2 ║
║ 3 ║ name3 ║
║ 4 ║ name5 ║
╚══════╩════════╝
Table B
╔═════╦════════╦════════╦═══════════╦═══════╗
║ ID ║ P_ID ║ C_ID ║ C_PRICE ║ TIME ║
╠═════╬════════╬════════╬═══════════╬═══════╣
║ 1 ║ 1 ║ 3 ║ 11 ║ 11111 ║
║ 2 ║ 2 ║ 4 ║ 22 ║ 22222 ║
║ 3 ║ 3 ║ 5 ║ 33 ║ 33333 ║
║ 4 ║ 3 ║ 6 ║ 44 ║ 44444 ║
║ 5 ║ 3 ║ 6 ║ 55 ║ 55555 ║
║ 6 ║ 4 ║ 7 ║ 66 ║ 66666 ║
╚═════╩════════╩════════╩═══════════╩═══════╝
The requirement is
1. Join two table
2. Group By C_ID
3. The latest rows in Group By
I tried to modify the answer By Bill Karwin from How do I join the most recent row in one table to another table?
SELECT e.*, s1.*
FROM table_a e
INNER JOIN
table_b s1
ON (e.p_id = s1.p_id)
LEFT OUTER JOIN table_b s2
ON (e.p_id = s2.p_id AND s1.id < s2.id)
WHERE s2.p_id IS NULL;
but I could not achieve what I want. From his answer I will get
╔═════╦════════╦════════╦═══════════╦═══════╦═════════╗
║ ID ║ P_ID ║ C_ID ║ C_PRICE ║ TIME ║ P_NAME ║
╠═════╬════════╬════════╬═══════════╬═══════╬═════════╣
║ 1 ║ 1 ║ 3 ║ 11 ║ 11111 ║ name1 ║
║ 2 ║ 2 ║ 4 ║ 22 ║ 22222 ║ name2 ║
║ 5 ║ 3 ║ 6 ║ 55 ║ 55555 ║ name3 ║
║ 6 ║ 4 ║ 7 ║ 66 ║ 66666 ║ name5 ║
╚═════╩════════╩════════╩═══════════╩═══════╩═════════╝
But the output what I want is as below ( dublicate P_ID is ok but for each dublicate P_ID should not have dublicate C_ID )
╔═════╦════════╦════════╦═══════════╦═══════╦═════════╗
║ ID ║ P_ID ║ C_ID ║ C_PRICE ║ TIME ║ P_NAME ║
╠═════╬════════╬════════╬═══════════╬═══════╬═════════╣
║ 1 ║ 1 ║ 3 ║ 11 ║ 11111 ║ name1 ║
║ 2 ║ 2 ║ 4 ║ 22 ║ 22222 ║ name2 ║
║ 3 ║ 3 ║ 5 ║ 33 ║ 33333 ║ name3 ║
║ 5 ║ 3 ║ 6 ║ 55 ║ 55555 ║ name3 ║
║ 6 ║ 4 ║ 7 ║ 66 ║ 66666 ║ name5 ║
╚═════╩════════╩════════╩═══════════╩═══════╩═════════╝
SELECT e.*, s1.*
FROM table_a e INNER JOIN
(SELECT * FROM (SELECT * FROM table_b ORDER BY time DESC) temp GROUP BY c_id) s1;
The innermost ORDER BY ensures the for the same c_id the desired row always comes first, the outter GROUP BY will group on c_id, and having not specified otherwise will return the first row found for each group.
You must
Join two table
Group By C_ID
Number row for each group desc ordered by chosen field (last imply order!)
Filter by row number = 1.
This can help you for numbering rows.