I have a 3 tables order, order_option, product_option
order
order_id | cus_name | cus_phone
-------------------------------
1 | Test-1 | 9876543211
2 | Test-2 | 9876543212
3 | Test-3 | 9876543213
4 | Test-4 | 9876543214
order_option
product_option_id | order_id
-------------------------------
11 | 1
12 | 1
13 | 2
14 | 4
15 | 3
product_option
product_id | product_option_id | sku | qty
------------------------------------------
1 | 11 | TS01 | 3
2 | 12 | TS02 | 2
3 | 13 | TS033 | 3
4 | 14 | TS023 | 3
Here I want to select order table and product_option table values with a where condition on the sku field.
i tried to join the query like below:
SELECT o.order_id, o.cus_name, o.cus_phone,po.sku,po.qty FROM order o
LEFT JOIN order_option op
ON (o.order_id = op.order_id)
LEFT JOIN product_option po
ON (op.product_option_id = po.product_option_id)
WHERE po.sku = "TS023"
But it's not showing the correct answer. I don't know what I have missed.
order is a reserved word, use backticks ``.
SELECT o.order_id, o.cus_name, o.cus_phone, po.sku, po.qty
FROM `order` o
LEFT JOIN order_option op ON o.order_id = op.order_id
LEFT JOIN product_option po ON op.product_option_id = po.product_option_id
WHERE po.sku = "TS023"
Output:
order_id cus_name cus_phone sku qty
4 Test-4 9876543214 TS023 3
SQL Fiddle: http://sqlfiddle.com/#!9/9b76b/2/0
Move the po condition from WHERE to ON to get true LEFT JOIN result:
SELECT o.order_id, o.cus_name, o.cus_phone,po.sku,po.qty FROM order o
LEFT JOIN order_option op
ON (o.order_id = op.order_id)
LEFT JOIN product_option po
ON (op.product_option_id = po.product_option_id)
AND po.sku = "TS023"
(When in WHERE, you'll get regular INNER JOIN result.)
#Matt is correct, here's another way of doing this.
SELECT o.order_id, o.cus_name, o.cus_phone, po.sku, po.qty
FROM `order` o, order_option op, product_option po
WHERE o.order_id = op.order_id
AND op.product_option_id = po.product_option_id
AND po.sku = "TSO23"
Related
I have 3 tables: foods, order_detail, and orders
Here are the records for table foods:
id | name | type
------------------------------
F01 | Omelette | Breakfast
F02 | Burger | Breakfast
F03 | Satay | Lunch
F04 | Fried Rice | Dinner
Here are the records for table order_detail:
food_id | order_id
-----------------------------
F01 | T01
F04 | T01
F02 | T02
F03 | T03
F03 | T04
And here are the records for orders table:
order_id | date | qty
---------------------------------
T01 | 2017-05-01 | 2
T02 | 2017-05-02 | 1
T03 | 2017-05-05 | 1
T04 | 2017-05-07 | 1
I want to show count order detail grouped by food type. I expected this result:
type | total_order
-------------------------
Breakfast | 2
Lunch | 2
Dinner | 1
Here is my approach, but it still doesn't show the expected result.
SELECT
f.type,
(SELECT COUNT(*) FROM order_detail od WHERE f.id = od.food_id) AS total_order
FROM foods f
LEFT JOIN order_detail od ON f.id = od.food_id
GROUP BY f.type
ORDER BY f.id
The result is:
type | total_order
-------------------------
Breakfast | 1
Lunch | 2
Dinner | 1
How can I get the result I want? Thanks in advance!
Aggregation can work here, but you need to join across all three tables:
SELECT f.type, COUNT(o.order_id) AS total_order
FROM foods f
LEFT JOIN order_detail od ON od.food_id = f.id
LEFT JOIN orders o ON o.order_id = od.order_id
GROUP BY f.type
ORDER BY f.id;
Note that we do a left join across all three tables in order to not drop any food type which might happen to have zero orders.
you can add the orderdtails to the subselect to get the correct number
SELECT
f.type,
(SELECT COUNT(*) FROM order_detail od2
WHERE f.id = od2.food_id AND od2.order_id = od.order_id
) AS total_order
FROM foods f
LEFT JOIN order_detail od ON f.id = od.food_id
GROUP BY f.type
ORDER BY f.id
WITH cte AS (
SELECT type
FROM foods
INNER JOIN order_detail ON (order_detail.food_id=foods.id)
INNER JOIN orders ON (order_detail.ord_id=orders.ord_id)
)
SELECT DISTINCT type, COUNT(type) OVER (PARTITION BY type) AS qty
FROM cte
I have the following tables and would like to get the result as follow
Table po
ID | Date
1 | 20-Jun-2016
Table podetails
ID | poid | itemcode | quantity
1 | 1 | SOAP123 | 100
Table poreceived
ID | poid | itemcode | quantity
1 | 1 | SOAP123 | 20
2 | 1 | SOAP123 | 60
Result should be:
PO | Date | itemcode | quantity
1 | 20-Jun-2016 | SOAP123 | 80
What I have done is:
SELECT
po.id, podetails.itemcode, poreceived.quantity
FROM
po
LEFT JOIN
podetails ON podetails.poid = po.id
LEFT JOIN
poreceived ON poreceived.poid = podetails.poid
But the result is not what I expected.
Any help would be appreciate it.
It looks like you need to do an aggregation of the poreceived table by poid. You can use a subquery for this:
SELECT po.id, COALESCE(podetails.itemcode, 'NA'), COALESCE(t.quantity, 0)
FROM po
LEFT JOIN podetails
ON podetails.poid = po.id
LEFT JOIN
(
SELECT poid, itemcode, SUM(quantity) AS quantity
FROM poreceived
GROUP BY poid, itemcode
) t
ON t.poid = podetails.poid AND t.itemcode = podetails.itemcode
Other than the aggregation problem, your query strategy looked correct. I also added COALESCE to the columns from the podetails and poreceived tables in case the id from po does not match to anything.
I would like to get the following results from my query:
id_product_attribute | id_product | reference | name | total
12 | 1 | 234235 | product_name | 2
14 | 2 | 235435 | product_name | 7
16 | 3 | 235325 | product_name | 4
etc
but when I use this query:
select pa.id_product_attribute, p.id_product, pa.reference, cl.name, sum(od.product_quantity) as total
from ps_product_attribute pa
left join ps_order_detail od on od.product_attribute_id = pa.id_product_attribute
left join ps_product p on pa.id_product = p.id_product
left join ps_category_product cp on cp.id_product = p.id_product
left join ps_category_lang cl on cp.id_category = cl.id_category
where cp.id_category = 141 and cl.id_lang = 6;
it gives me only this results:
id_product_attribute | id_product | reference | name | total
12 | 1 | 234235 | product_name | 13
so in the 'total' column it shows me the total of all, instead of seperate per row.
can anyone tell me what I'm doing wrong in my query?
Your source data would help, but at the very least you forgot to GROUP BY at the end. With the current query, you should add;
GROUP BY pa.id_product_attribute, p.id_product, pa.reference, cl.name
With MySQL, you can choose to GROUP BY less columns and get a random selection of values in the other ones, but if possible, you should GROUP BY all columns that don't have aggregates (like SUM in this case) on them.
Aggregate functions should be used with GROUP BY CLAUSE
Query below currently shows the total as item by item but what I want is to calculate subtotal of all items in a purchase order.
Thanks
Output should be:
POID Item ItemQTY ItemPrice ItemTotal SubTotal
1 A 1 15.00 15.00 80.50
1 B 1 25.50 25.50 80.50
1 C 2 20.00 40.00 80.50
2 X 6 5.00 30.00 50.00
2 Y 2 10.00 20.00 50.00
Relationship: purchase_order 1 - N purchase_order_items
SELECT
purchase_order.id AS POID,
purchase_order_items.description AS Item,
purchase_order_items.quantity AS ItemQTY,
purchase_order_items.price AS ItemPrice,
(purchase_order_items.quantity*purchase_order_items.price) AS ItemTotal
/* Here, Subtotal should be calculated and displayed */
FROM purchase_order
INNER JOIN purchase_order_items ON purchase_order.id = purchase_order_items.fk_purchase_order
I looked at MySQL finding subtotals and Subtotals and SQL but couldn't apply to my query.
You can use the WITH ROLLUP feature to get subtotals:
SELECT
purchase_order.id AS POID,
purchase_order_items.description AS Item,
purchase_order_items.quantity AS ItemQTY,
purchase_order_items.price AS ItemPrice,
SUM(purchase_order_items.quantity*purchase_order_items.price) AS ItemTotal
FROM purchase_order
INNER JOIN purchase_order_items ON purchase_order.id = purchase_order_items.fk_purchase_order
GROUP BY POID, Item WITH ROLLUP
This will create a result set that has Item = NULL for the PO subtotal, and POID = NULL for a grand total. These subtotals and grand totals go in the ItemTotal column of those rows.
Try
SELECT i.fk_purchase_order POID,
description Item,
quantity ItemQTY,
price ItemPrice,
quantity * price ItemTotal,
s.subtotal SubTotal
FROM purchase_order_items i JOIN
(
SELECT fk_purchase_order, SUM(quantity * price) subtotal
FROM purchase_order_items
GROUP BY fk_purchase_order
) s ON i.fk_purchase_order = s.fk_purchase_order
Output:
| POID | ITEM | ITEMQTY | ITEMPRICE | ITEMTOTAL | SUBTOTAL |
------------------------------------------------------------
| 1 | A | 1 | 15 | 15 | 80.5 |
| 1 | B | 1 | 25.5 | 25.5 | 80.5 |
| 1 | C | 2 | 20 | 40 | 80.5 |
| 2 | X | 6 | 5 | 30 | 50 |
| 2 | Y | 2 | 10 | 20 | 50 |
Here is SQLFiddle demo
Afraid I think the best solution is to cross join against a subselect:-
SELECT
purchase_order.id AS POID,
purchase_order_items.description AS Item,
purchase_order_items.quantity AS ItemQTY,
purchase_order_items.price AS ItemPrice,
(purchase_order_items.quantity*purchase_order_items.price) AS ItemTotal,
Sub1.FullTotal
FROM purchase_order
INNER JOIN purchase_order_items ON purchase_order.id = purchase_order_items.fk_purchase_order
CROSS JOIN
(
SELECT SUM(purchase_order_items.quantity*purchase_order_items.price) AS FullTotal
FROM purchase_order
INNER JOIN purchase_order_items ON purchase_order.id = purchase_order_items.fk_purchase_order
) Sub1
To bring it back for grouped purchase order ids
SELECT
purchase_order.id AS POID,
purchase_order_items.description AS Item,
purchase_order_items.quantity AS ItemQTY,
purchase_order_items.price AS ItemPrice,
(purchase_order_items.quantity*purchase_order_items.price) AS ItemTotal,
Sub1.FullTotal
FROM purchase_order
INNER JOIN purchase_order_items ON purchase_order.id = purchase_order_items.fk_purchase_order
INNER JOIN
(
SELECT purchase_order.id, SUM(purchase_order_items.quantity*purchase_order_items.price GROUP BY purchase_order.id) AS FullTotal
FROM purchase_order
INNER JOIN purchase_order_items ON purchase_order.id = purchase_order_items.fk_purchase_order
) Sub1
ON purchase_order.id = Sub1.id
I got a "Empresas" table
dbo.empresas
id | name | delegacion_id
-------------------------
1 | A | 3
2 | B | 3
3 | C | 3
4 | D | 4
a "pagos" table
dbo.pagos
id | id_empresa | monto | periodo
----------------------------------
1 | 1 | 120 | 2012-11-01
2 | 1 | 125 | 2012-12-01
3 | 2 | 150 | 2012-11-01
4 | 1 | 200 | 2013-01-01
5 | 2 | 151 | 2012-12-01
I have a value X that is a percentage.
I need to show the "empresas" that, comparing the "montos" of their two last "pagos" (ordered by periodo), have changed at least +X% or -X%, from an especific id_delegacion
For example, if we run this query with these example values, considering
X = 10
id_delegacion = 3
the output expected will be:
name | periodo | monto
---------------------------
A | 2012-12-01 | 125
A | 2013-01-01 | 200
empresa A is from delegacion_id = 3, and the comparison between the last two pagos, ordered by periodo desc (200 => 125) is bigger than 10%.
B is not showed because the comparison is smaller than 10%.
C is not showed because has no row in "pagos" table
D is from another delegation.
How can I get this desired output? For the record, using MySQL 5.5.8.
What I've done
I got this
select P.id_empresa, max(periodo) as periodo from
pagos P
where id_empresa in(
select e.id
from empresa E
where E.id_delegacion = 3
)
group by p.id_empresa, p.periodo
having count(*) > 1
with these I got the "empresas" that have more than one "pago" row, and got id_delegation = 3.
Also get the first period (the maximum), but I don't know how to get the second for each empresa, and compare them.
thanks
This is my query:
SELECT
empresas.name,
pagos.periodo,
pagos.monto
FROM
pagos INNER JOIN (
SELECT
lst.id id1,
prc.id id2
FROM (
SELECT
p1.id_empresa,
MAX(p1.periodo) last_p,
MAX(p2.periodo) prec_p
FROM
pagos p1 INNER JOIN pagos p2
ON p1.id_empresa = p2.id_empresa
AND p2.periodo < p1.periodo
GROUP BY
id_empresa) latest
INNER JOIN
pagos lst ON lst.id_empresa = latest.id_empresa AND lst.periodo=latest.last_p
INNER JOIN
pagos prc ON prc.id_empresa = latest.id_empresa AND prc.periodo=latest.prec_p
WHERE
lst.monto > prc.monto * 1.1) ids
ON pagos.id IN (ids.id1, ids.id2)
INNER JOIN
empresas
ON pagos.id_empresa = empresas.id
WHERE
delegacion_id=3
I think it can be simplified if you want to have values on the same row, e.g.
name | ultimo_periodo | ultimo_monto | anterior_periodo | anterior_monto
Please see fiddle here.
I still wondering if it can be simplified a little, but I am not sure if it is. Here's another solution:
SELECT
empresas.name,
pagos.periodo,
pagos.monto
FROM
pagos INNER JOIN empresas
ON pagos.id_empresa = empresas.id
INNER JOIN (
SELECT
id_empresa,
MAX(CASE WHEN row=1 THEN monto END) lst_monto,
MAX(CASE WHEN row=2 THEN monto END) prc_monto,
MAX(id) id1, MIN(id) id2
FROM (
SELECT
p1.*, COUNT(*) row
FROM
pagos p1 INNER JOIN pagos p2
ON p1.id_empresa = p2.id_empresa
AND p1.periodo <= p2.periodo
INNER JOIN empresas
ON p1.id_empresa = empresas.id
WHERE
empresas.delegacion_id = 3
GROUP BY
p1.id, p1.id_empresa, p1.monto, p1.periodo
HAVING
COUNT(*)<=2
ORDER BY
p1.id_empresa, p1.periodo desc
) s
GROUP BY
id_empresa
HAVING
lst_monto>prc_monto*1.1
) l ON pagos.id IN (l.id1, l.id2)
Please see fiddle here.