This question already has answers here:
MySQL Results as comma separated list
(4 answers)
Closed 5 years ago.
I'm new to MYSQL and struggling to form a query that joins two tables and returns a unique product row.
TABLE product:
╔══════════════════════════════╦══════════╦════════════╦════════════════════╗
║ ref ║ brand ║ mpn ║ sku ║
╠══════════════════════════════╬══════════╬════════════╬════════════════════╣
║ 0001___DOGICLON___912-101242 ║ DOGICLON ║ 912-101242 ║ 000000000001082649 ║
║ 0002___DOGICLON___912-101242 ║ DOGICLON ║ 912-101242 ║ 912-101242 ║
║ 0003___Dogiclon___912-101242 ║ Dogiclon ║ 912-101242 ║ 912-101242(R400) ║
║ 0005___Dogiclon___912-101242 ║ Dogiclon ║ 912-101242 ║ MILT-R400 ║
╚══════════════════════════════╩══════════╩════════════╩════════════════════╝
TABLE inventory:
╔══════════════════════════════╦═══════╦═════════╦══════════╗
║ ref ║ scost ║ instock ║ location ║
╠══════════════════════════════╬═══════╬═════════╬══════════╣
║ 0001___DOGICLON___912-101242 ║ 53.68 ║ 24 ║ WA ║
║ 0001___DOGICLON___912-101242 ║ 53.68 ║ 0 ║ CA ║
║ 0002___DOGICLON___912-101242 ║ 61.00 ║ 121 ║ WA ║
║ 0003___Dogiclon___912-101242 ║ 53.53 ║ 100 ║ WA ║
║ 0003___Dogiclon___912-101242 ║ 53.53 ║ 0 ║ NY ║
║ 0003___Dogiclon___912-101242 ║ 53.53 ║ 20 ║ MA ║
║ 0003___Dogiclon___912-101242 ║ 53.53 ║ 2 ║ CA ║
║ 0005___Dogiclon___912-101242 ║ 56.00 ║ 5 ║ IN ║
║ 0005___Dogiclon___912-101242 ║ 56.00 ║ 5 ║ MA ║
║ 0005___Dogiclon___912-101242 ║ 56.00 ║ 5 ║ WA ║
║ 0005___Dogiclon___912-101242 ║ 56.00 ║ 5 ║ NY ║
║ 0005___Dogiclon___912-101242 ║ 56.00 ║ 2 ║ CA ║
╚══════════════════════════════╩═══════╩═════════╩══════════╝
I guess pseduo code would be:
SHOW all products
WHERE
instock (any location) > 0 AND
(cost > 10 AND cost < 2000)
ORDER BY
cost asc
Notes:
refs are unique per supplier
brand and mpn lookup needs to be
case insensitive
Expected Result:
╔══════════╦══════════╦════════════╦══════════════╦══════════════╦═══════════════════════════╗
║ ref ║ brand ║ mpn ║ sku ║ scost ║ instock ║
╠══════════╬══════════╬════════════╬══════════════╬══════════════╬═══════════════════════════╣
║ whatever ║ Dogiclon ║ 912-101242 ║ based on ref ║ based on ref ║ based on ref and location ║
╚══════════╩══════════╩════════════╩══════════════╩══════════════╩═══════════════════════════╝
This is what I'm trying:
SELECT DISTINCT
product.ref,
product.brand,
inventory.scost,
inventory.instock
FROM
product
JOIN inventory ON inventory.ref = product.ref
WHERE
inventory.instock > 1
AND ( app.inventory.scost >= 10 AND app.inventory.scost <= 2000 )
GROUP BY
product.ref
If you are grouping by unique column within product which seems to be ref, distinct won't do what you wish it would. DISTINCT takes care of uniqueness per returned row (all values being returned). In this case to get one row in result per product ref you'd need to drop the distinct part, add product.mfr to group by and aggregate non-grouped columns like below:
SELECT
product.ref,
product.mfr,
group_concat(inventory.scost) as scost,
group_concat(inventory.instock) as instock,
FROM
product
JOIN inventory ON inventory.ref = product.ref
WHERE
inventory.instock > 1
AND ( app.inventory.scost >= 10 AND app.inventory.scost <= 2000 )
GROUP BY
product.ref, product.mfr
If you want to ensure proper ordering for scost and instock just include ordering clause within the group_concat itself ie:
group_concat(column order by column1, [...])
Related
I have a table of orders which follows the below format:
╔══════════╦══════════╦══════════╦═══════╦══════════════╦═══════════════╗
║ Order ID ║ Subtotal ║ Shipping ║ Total ║ Product Name ║ Product Price ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 1 ║ 30 ║ 5 ║ 35 ║ Apple ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 1 ║ ║ ║ ║ Banana ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 1 ║ ║ ║ ║ Coffee ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 2 ║ 30 ║ 5 ║ 35 ║ Peach ║ 20 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 2 ║ ║ ║ ║ Banana ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 3 ║ 20 ║ 3 ║ 23 ║ Peach ║ 20 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 4 ║ 40 ║ 10 ║ 50 ║ Apple ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 4 ║ ║ ║ ║ Coffee ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 4 ║ ║ ║ ║ Peach ║ 20 ║
╚══════════╩══════════╩══════════╩═══════╩══════════════╩═══════════════╝
All order numbers come as totals - subtotal and shipping with the lines below blank.
I am trying to look into the sales of a specific product.
For example I'd like to have a query which selects all orders which contain "Banana" and also returns the subtotal, shipping and total for the order as well as the product price (which are sometimes not on the same line):
I.e. it'd return this:
╔══════════╦══════════╦══════════╦═══════╦══════════════╦═══════════════╗
║ Order ID ║ Subtotal ║ Shipping ║ Total ║ Product Name ║ Product Price ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 1 ║ 30 ║ 5 ║ 35 ║ Banana ║ 10 ║
╠══════════╬══════════╬══════════╬═══════╬══════════════╬═══════════════╣
║ 2 ║ 30 ║ 5 ║ 35 ║ Banana ║ 10 ║
╚══════════╩══════════╩══════════╩═══════╩══════════════╩═══════════════╝
You can join the table to itself:
select
b.`Order ID`,
max(s.Subtotal) as 'Subtotal',
max(s.Shipping) as 'Shipping',
max(s.Total) as 'Total',
b.`Product Name`,
b.`Product Price`
from orders b
join orders s on s.`Order ID`=b.`Order ID`
where b.`Product Name`='Banana'
group by
b.`Order ID`,
b.`Product Name`,
b.`Product Price`
See a dbfiddle.
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
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 columns in a table say, LIKE and FAVORITES (int value)
See the chart:
╔════╦══════╦══════════╗
║ ID ║ LIKE ║ FAVORITE ║
╠════╬══════╬══════════╣
║ 1 ║ 25 ║ 9 ║
║ 2 ║ 5 ║ 17 ║
║ 3 ║ 6 ║ 1 ║
║ 4 ║ 45 ║ 0 ║
║ 5 ║ 3 ║ 44 ║
╚════╩══════╩══════════╝
Now, I want to select the Maximum Like and Favorites IDs from the SELECT clause.
I have tried
SELECT ID from TABLE WHERE CONDITION ORDER BY LIKE,FAVORITES DESC
But the result shows the rows based on LIKE DESC order.
The result should be
╔════╗
║ ID ║
╠════╣
║ 5 ║
║ 4 ║
║ 1 ║
║ 2 ║
║ 3 ║
╚════╝
I think you need to add those two columns. eg,
SELECT ID
FROM tableName
ORDER BY `LIKE` + FAVORITE DESC
SQLFiddle Demo
Result:
╔════╗
║ ID ║
╠════╣
║ 5 ║
║ 4 ║
║ 1 ║
║ 2 ║
║ 3 ║
╚════╝
For example if I have a table called sales with the values:
╔════════╦═══════╗
║ ITEM ║ SALES ║
╠════════╬═══════╣
║ record ║ 4 ║
║ cd ║ 2 ║
║ cd ║ 5 ║
║ record ║ 1 ║
╚════════╩═══════╝
How would I write a query to sort by the sum of distinct items so that my output is:
╔════════╦════════════╗
║ ITEM ║ TOTALSALES ║
╠════════╬════════════╣
║ cd ║ 7 ║
║ record ║ 5 ║
╚════════╩════════════╝
use GROUP BY and SUM()
SELECT item, SUM(sales) totalSales
FROM sales
GROUP BY item
SQLFiddle Demo
The output:
╔════════╦════════════╗
║ ITEM ║ TOTALSALES ║
╠════════╬════════════╣
║ cd ║ 7 ║
║ record ║ 5 ║
╚════════╩════════════╝