MySQL LEFT JOIN multiple rows from TableB - mysql

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

Related

Select all customers and all orders with single query

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;

using condition for Group_Concat

I want to find all ids of which group_concat only contains 'a'.
Here is simplified table from mine.
╔════╦══════════════╦
║ id ║ group_concat ║
╠════╬══════════════╬
║ 1 ║ a,b,b ║
║ 2 ║ a ║
║ 3 ║ a,a ║
║ 4 ║ a,a,a ║
║ 5 ║ a,b,a ║
╚════╩══════════════╩
And the table below is what I want to achieve.
╔════╦══════════════╦
║ id ║ group_concat ║
╠════╬══════════════╬
║ 2 ║ a ║
║ 3 ║ a,a ║
║ 4 ║ a,a,a ║
╚════╩══════════════╩
And this is the query statement I am trying to use.
select id, group_concat(val)
from user
group by id
having group_concat(val) = 'a'
Thanks in advance
Try this:
select id, group_concat(val)
from user
group by id
having count(distinct val) = 1 and max(val) = 'a'

How to get corresponding id with minimum value of a row in MySQL?

I have two tables named deals and mp_details. Columns deal_id and mp_details_id are the two primary keys. There is a relation between the two tables using the deal_mp_id column where it works as a foreign key. I want to fetch all the minimum records of column name deal_selling_price with group by mp_details_id. Here are the tables:
deals
╔═════════╦════════════╦════════════════════╗
║ deal_id ║ deal_mp_id ║ deal_selling_price ║
╠═════════╬════════════╬════════════════════╣
║ 3 ║ 1 ║ 425 ║
║ 4 ║ 1 ║ 540 ║
║ 5 ║ 2 ║ 340 ║
║ 6 ║ 2 ║ 315 ║
║ 7 ║ 3 ║ 425 ║
║ 8 ║ 3 ║ 720 ║
║ 9 ║ 4 ║ 382.5 ║
║ 10 ║ 4 ║ 495 ║
║ 11 ║ 5 ║ 595 ║
║ 12 ║ 5 ║ 720 ║
╚═════════╩════════════╩════════════════════╝
mp_details
╔═══════════════╦═════════════════════╗
║ mp_details_id ║ mp_details_name ║
╠═══════════════╬═════════════════════╣
║ 1 ║ Olive Bar & Kitchen ║
║ 2 ║ Thai High ║
║ 3 ║ Tonino ║
║ 4 ║ Impromptu ║
║ 5 ║ Zerruco ║
╚═══════════════╩═════════════════════╝
And I want this kind of result:
╔═════════╦════════════╦════════════════════╗
║ deal_id ║ deal_mp_id ║ deal_selling_price ║
╠═════════╬════════════╬════════════════════╣
║ 3 ║ 1 ║ 425 ║
║ 6 ║ 2 ║ 315 ║
║ 7 ║ 3 ║ 425 ║
║ 9 ║ 4 ║ 382.5 ║
║ 11 ║ 5 ║ 595 ║
╚═════════╩════════════╩════════════════════╝
The following query will give you the result set from your screen capture above:
SELECT d1.deal_id, d1.deal_mp_id, d2.minPrice
FROM deals d1
INNER JOIN
(
SELECT deal_mp_id, MIN(deal_selling_price) AS minPrice
FROM deals
GROUP BY deal_mp_id
) d2
ON d1.deal_mp_id = d2.deal_mp_id AND d1.deal_selling_price = d2.minPrice
If you also want to include information from the mp_details table, you can do an additional join like this:
SELECT d1.deal_id, d1.deal_mp_id, d2.minPrice, mp.mp_details_name
FROM deals d1
INNER JOIN
(
SELECT deal_mp_id, MIN(deal_selling_price) AS minPrice
FROM deals
GROUP BY deal_mp_id
) d2
ON d1.deal_mp_id = d2.deal_mp_id AND d1.deal_selling_price = d2.minPrice
INNER JOIN mp_details mp
ON d1.deal_mp_id = mp.mp_details_id
Follow the link below for a running demo:
SQLFiddle
Try below query
select
D.Deal_id, MD.mp_details_id, MIN(D.deal_selling_price)
FROM
deals D inner join mp_details MD
ON
D.Deal_id = MD.mp_details_id
GROUP BY
D.Deal_id, MD.mp_details_id
Use this query:
SELECT d.deal_id, d.deal_mp_id, d.deal_selling_price
FROM deals d
JOIN
(
SELECT deal_mp_id, MIN(deal_selling_price) AS min_selling_price
FROM deals
GROUP BY deal_mp_id
) m
ON d.deal_mp_id = m.deal_mp_id AND d.deal_selling_price = m.min_selling_price

How to merge two sql tables where B is a subset of A and should override A?

Table A (nothing is unique)
╔══════╦══════╦═══════════╦═══════════════╗
║ p_id ║ l_id ║ p_name ║ p_description ║
╠══════╬══════╬═══════════╬═══════════════╣
║ 212 ║ 1 ║ Ball ║ Red ║
║ 212 ║ 2 ║ Balle ║ Rouge ║
║ 301 ║ 1 ║ Horn name ║ Blue ║
╚══════╩══════╩═══════════╩═══════════════╝
Table B (p_id is unique)
╔══════╗
║ p_id ║
╠══════╣
║ 101 ║
║ 201 ║
║ 210 ║
║ 212 ║
║ 234 ║
║ 250 ║
║ 301 ║
║ 320 ║
╚══════╝
W.r.t p_id, Table A is a subset of Table B (all p_id should exist in Table B) but Table A contains different data. Both tables contain a lot more columns that I'm not showing. For table A I'm only concerned with the p_id. For table B I want to eliminate duplicates based on l_id. There will always be an entry with l_id of 1 but there may or may not be others which should be discarded (ie. a simple WHERE l_id=1 should do).
The result should be a table that has every p_id of Table B (once) with every column of Table A. Most of the rows will have no data in those other columns, because they didn't exist in Table B. So I should have this, for example:
╔══════╦══════╦═══════════╦═══════════════╗
║ p_id ║ l_id ║ p_name ║ p_description ║
╠══════╬══════╬═══════════╬═══════════════╣
║ 101 ║ ║ ║ ║
║ 201 ║ ║ ║ ║
║ 210 ║ ║ ║ ║
║ 212 ║ 1 ║ Ball ║ Red ║
║ 234 ║ ║ ║ ║
║ 250 ║ ║ ║ ║
║ 301 ║ 1 ║ Horn name ║ Blue ║
║ 320 ║ ║ ║ ║
╚══════╩══════╩═══════════╩═══════════════╝
From your description, this sounds like a left join:
select b.p_id, a.l_id, a.p_name, a.p_description
from b left join
a
on b.p_id = a.p_id and a.l_id = 1;
To get all rows from one table and the rows matching some condition from another you can use a left join:
select b.p_id, a.l_id, a.p_name, a.p_description
from b
left join a on b.p_id = a.p_id and a.l_id = 1
This will get you everything from B with values for the columns in A matching the where condition. For those rows in B that doesn't have any matches you'll get null values.

mysql - combining 2 tables with different condition

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);