I have 2 tables, orders and order_lineitems.
orders contains the order status info (sold date, invoice no, type of sale, etc)
order_lineitems contains the item(s) for each order in a one to many relationship.
Since we provide shipping info by line item, ship_date is in the order_lineitems table, null if not shipped, a date if it is shipped.
I am trying to pull the orders where all items have shipped by comparing the number of line item rows against the line item rows that have a ship date. While I have successfully pulled all that info, I am unable to make the last step, limiting the result set to include only the completely shipped orders (number of rows = number of rows where ship_date is not null).
I know I am missing something simple, but just don't see it..
select sum(custom.lineitems) as totalitems, sum(custom.shipped) as totalshipped,
custom.invoice, z.shipregion
from (
select a.invoice, count(a.invoice) as lineitems, 0 as shipped
from order_lineitem a
group by a.invoice
UNION ALL
select b.invoice, 0 as notshipped, count(b.ship_date) as shipped
from order_lineitem b
where b.ship_date is not null
group by b.invoice
) as custom
left join orders z on custom.invoice = z.invoice
where z.result = 0
and z.respmsg like 'Approved%'
and z.shipregion <> 'PENDING'
and z.cancelorder = 0
group by custom.invoice;
This returns a result set like so (one row for each invoice in the DB)
totalitems totalshipped invoice shipregion
4 2 1000 REGION08
1 1 10001 REGION07
1 1 10004 REGION05
3 1 10006 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
What I am looking for is a result set like this - only where totalitems = totalshipped
totalitems totalshipped invoice shipregion
1 1 10001 REGION07
1 1 10004 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
Use HAVING clause
SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice HAVING lineitems = shipped
OR
SELECT a.invoice, a.shipregion, a.lineitems, a.shipped
FROM (SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice
) AS a WHERE a.lineitems = a.shipped
One more outer query needed.
select * from
(
\\Your whole query here
) as Result
where Result.totalitems = Result.totalshipped
Related
im trying to make a column for month 1, 2 and 3 and put the invoice's total in that column. I have made that successfully, but then below there are more columns with zeroes for every column, aka it shows me the column for every invoice, but I want to get ONLY the invoices that have been made in month 1,2 and 3 and don't show the rest. How do I do that?
what I get:
invoice_id | total | firstMonth | secondMonth | thirdMonth |
1 33.4 0 0 33.4
2 3434.5 0 0 0 <=====
what I want:
invoice_id | total | firstMonth | secondMonth | thirdMonth |
1 33.4 0 0 33.4
Please learn about types. Single quotes should be used for string and date constants -- and not for column identifiers or numbers.
Then, I think you just want to filter the results correctly:
SELECT i.id AS invoice_ID , i.total AS TOTAL,
(CASE WHEN month(i.datetime) = 1 THEN ABS(i.total) ELSE 0 END) AS firstMonth,
(CASE WHEN month(i.datetime) = 2 THEN ABS(i.total) ELSE 0 END) AS secondMonth,
(CASE WHEN month(i.datetime) = 3 THEN ABS(i.total) ELSE 0 END) AS thirdMonth
FROM invoice i JOIN
store s
ON i.store_id = s.id JOIN
company c
ON s.company_id = c.id
WHERE c.name = 'RubberDuck' AND
i.datetime >= '2019-01-01' AND
i.date_time < '2019-04-01'
I have 3 table request, plan, level.
Here is table request:
id plan_id response_code client_id
1 1 200 1
2 1 200 1
3 1 400 1
4 1 500 1
Here is table plan:
id client_id
1 1
2 1
3 1
4 1
Here is table price:
id plan_id
1 1
2 2
3 3
4 4
I want join 3 table and count in table request, how many record with response_code 200, 400, and 500. But I get wrong value. Here is my query
SELECT
requests.id,
SELECT SUM(case
when requests.response_code = 200 then
1 else 0
end) as resquest200,
SELECT SUM(case
when requests.response_code = 500 then
1 else 0
end) as resquest500,
response_code,
FROM requests
JOIN plan
ON requests.plan_id = plan.id
JOIN price
ON plan.id = price.plan_id
GROUP BY request.id
I tried:
SELECT
request.id,
(
SELECT SUM(case
when request.response_code = 200 then
1 else 0
end) FROM request) as resquest200,
response_code,
FROM request
JOIN plan
ON requests.plan_id = plan.id
JOIN price
ON plan.id = price.plan_id
GROUP BY request.id
and it sum correctly. How can I optimize my query? Please help me
If you're looking to establishing the total number of requests then COUNT() is a better option than SUM()
SELECT COUNT(*), response_code FROM requests
GROUP BY response_code
Why do you want to join onto plan and price? Is there some data that from these tables that you need to return?
I have two table
ORDER
prod_id qty gst gst_rate
1 25 yes 18
1 25 no 0
2 10 yes 12
3 5 no 0
RETURN
prod_id add less gst_rate
1 5 0 0
1 10 0 18
3 0 2 0
About the table ORDER
Product 1 have order 25 with gst 18% and order 25 without gst. Product
2 have order 10 with gst 12%. Product 3 have order 5 without gst.
About the table Return
Product 1 without gst have extra qty 5. Product 1 with gst have extra
qty 10. Product 3 (no gst) have less qty 2. Product 2 have no extra or
less qty.
So I have to create a VIEW for each entry in ORDER table
Result should look like this
prod_id qty gst_rate add less
1 25 18 10 0
1 25 0 5 0
2 10 12 0 0
3 5 0 0 2
What I tried is:
SELECT ord.prod_id, ord.qty, ord.gst_rate, ret.add, ret.less FROM order ord LEFT JOIN (SELECT case when ord.gst='no' then (select sum(add) from return,order where order.prod_id=return.prod_id and return.gst_rate=0) else (select sum(add) from return,order where order.prod_id=return.prod_id and return.gst_rate!=0) end as add FROM return) as ret ON ret.prod_id=ord.prod_id
But it is not working..
you query could be refactored avoiding subquery ..
SELECT ord.prod_id, ord.qty, ord.gst_rate,
case when rd.gst='no' then t1.sum_add else t2.sum_add end as add
FROM order ord
LEFT JOIN (
select prod_id, sum(add) as sum_add
from return
INNER JOIN order ON order.prod_id=return.prod_id and return.gst_rate=0
GROUP BY prod_id
) t1 on t1.prod_id = ord.prod_id
LEFT JOIN (
select prod_id, sum(add) as sum_add
from return
INNER JOIN order ON order.prod_id=return.prod_id and return.gst_rate!=0
GROUP BY prod_id
) t2 on t2.prod_id = ord.prod_id
(the less was not in you code so i have omitted by select )
So I intend to Query data for a couple of charts in MySQL,
The data for the charts come from the same table, but work for multiple Time ranges. So group by doesn't work.
The Date itself I want in the format
Total Oranges Mangoes Bananas Tomatoes
----------------------------------------------
19 5 6 7 1
24 3 7 2 12
14 3 4 5 2
20 5 7 6 2
Now, I can get the Initial row using either
SELECT
sum(CASE WHEN Some_Criteria and (created between '2016-03-28' AND '2016-03-29')) THEN 1 ELSE 0 END ) Total ,
sum(CASE WHEN Some_Other_Criteria and (created between '2016-03-28' AND '2016-03-29')) THEN 1 ELSE 0 END ) Oranges
...
from SomeTable.Table1
left join OtherTable ON SomeId = OtherId
OR via
SELECT
(SELECT count(distinct Field) FROM from SomeTable.Table1 left join OtherTable ON SomeId = OtherId WHERE SomeCriteria and (DateRange)) AS Total
(SELECT count(distinct Field) FROM from SomeTable.Table1 left join OtherTable ON SomeId = OtherId WHERE SomeCriteria and (DateRange)) AS Oranges
...
Getting it in the same row would be easy as I just use the above method, but what if I want the data to be in multiple rows but based on the different date ranges?
You'll need those date ranges in a resultset (either a subquery, a temporary table, or a permanent table of some sort). Once you have that you can use your first query with a JOIN to your ranges table and then using GROUP BY on those ranges.
For example:
SELECT
DR.start_date,
DR.end_date,
SUM(CASE WHEN Some_Criteria AND (created BETWEEN DR.start_date AND DR.end_date)) THEN 1 ELSE 0 END ) Total,
SUM(CASE WHEN Some_Other_Criteria AND (created BETWEEN DR.start_date AND DR.end_date)) THEN 1 ELSE 0 END ) Oranges,
...
FROM
Date_Ranges DR
INNER JOIN SomeTable.Table1 T1 ON
T1.created >= DR.start_date AND
T1.created < DR.end_date
LEFT OUTER JOIN OtherTable OT ON OT.SomeId = T1.OtherId
GROUP BY
DR.start_date,
DR.end_date
I am not sure if my question is clear but what I need is quite complex query. I am unable to put it together myself.
We have tables orders, order_items, products, deliveries and delivery_items. Orders is the main order table. Order_items table holds the list of ordered products in certain order. Products is the main products table and deliveries/delivery_items tables hold the list of delivered order_items (we can deliver entire order or only partially).
This is the 'stripped down' table structure:
ORDERS:
ID ORDER_NUMBER DELIVERY_DATE STATUS
-------------------------------------------------
1 2013-00001 Unixtimestamp Closed
2 2013-00002 Unixtimestamp Open
...
PRODUCTS:
ID CODE
-----------------------
1 Product 1
2 Product 2
3 Product 3
...
ORDER ITEMS:
ID ORDER_ID PRODUCT_ID QTY
-----------------------------------------
1 1 1 2
2 1 2 5
3 1 3 1
4 2 3 10
DELIVERIES:
ID ORDER_ID DELIVERY_NUMBER TYPE
---------------------------------------------
1 1 2013-00001 Full
2 2 2013-00002 Partial
...
DELIVERY_ITEMS:
ID DELIVERY_ID ORDER_ITEM_ID QTY
------------------------------------------
1 1 1 2
2 1 2 5
3 1 3 1
4 2 4 5
...
Our production demands view where all non-delivered order_items(products) are listed by quantities in the upcoming week schedule. What I need is something like this (quantities here are random):
Product Overdue W0 W1 W2 W3 W4 W5 Later Total
-------------------------------------------------------------------------
Product 1 1 2 0 0 0 0 0 0 3
Product 2 0 3 5 1 0 0 0 4 13
Product 3 2 4 0 7 5 0 0 0 18
...
The entire view is based on current time and order's delivery_date field. The query would need to get ordered product quantities from all open orders, check if some of there products were maybe already delivered and subtract delivered quantities, and on the end sort the result quantities as shown above.
UPDATE: here is SQL Fiddle with above structure with some data http://sqlfiddle.com/#!2/88891/4
---Using Fiddle provided (http://sqlfiddle.com/#!2/88891/34/0)
SELECT P.Name,
sum(case when DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())<=0 then coalesce(OI.Quantity,0)-coalesce(DI.Quantity,0) else 0 END) AS Overdue,
sum(case when DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())<=7 and DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())>0 then coalesce(OI.Quantity,0)-coalesce(DI.Quantity,0) else 0 END) as W0,
sum(case when DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())<=14 and DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())>7 then coalesce(OI.Quantity,0)-coalesce(DI.Quantity,0) else 0 END) as W1,
sum(case when DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())<=21 and DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())>14 then coalesce(OI.Quantity,0)-coalesce(DI.Quantity,0) else 0 END) as W2,
sum(case when DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())<=28 and DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())>21 then coalesce(OI.Quantity,0)-coalesce(DI.Quantity,0) else 0 END) as W3,
sum(case when DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())<=35 and DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())>28 then coalesce(OI.Quantity,0)-coalesce(DI.Quantity,0) else 0 END) as W4,
sum(case when DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())<=42 and DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())>35 then coalesce(OI.Quantity,0)-coalesce(DI.Quantity,0) else 0 END) as W5,
sum(case when DATEDIFF(FROM_UNIXTIME(Delivery_date),curDate())>42 then coalesce(OI.Quantity,0)-coalesce(DI.Quantity,0) else 0 END) as Later,
sum(coalesce(OI.Quantity,0)-coalesce(DI.Quantity,0)) as Total
FROM ORDERS O
INNER JOIN ORDER_ITEMS OI
ON OI.Order_ID = O.ID
INNER JOIN PRODUCTS P on
P.ID = OI.Product_ID
LEFT JOIN DELIVERIES D
ON D.Order_ID = O.ID
LEFT JOIN DELIVERY_ITEMS DI
ON DI.Delivery_ID = D.ID
AND OI.ID = DI.Order_Item_ID
WHERE coalesce(DI.Quantity,0) < OI.Quantity
GROUP BY P.Name
Thanks for the fiddle. This takes care of all the remaining syntax errors. and formats to include 0 in the results.
Coalesce, takes first non-null value in an unlimited series.
FROM_UNIXTIME converts into to valid date time for comparison using datediff.
else statments handle situations when no data matches critiera thus 0 is
evaluated.
where clause eliminates orders with all items delivered or more than all items ordered delivered. (Thus items closed will still be included since they are not fully shipped!)
To get you started, here are a couple of joins:
SELECT o.ORDER_NUMBER, p.CODE, oi.QTY
FROM orders o
JOIN order_items oi ON oi.ORDER_ID = o.ID
JOIN products p ON p.ID = oi.PRODUCT_ID
And:
SELECT d.DELIVERY_NUMBER, d.ORDER_ID, di.ORDER_ITEM_ID, di.QTY
FROM deliveries d
JOIN delivery_items di ON di.DELIVERY_ID = d.ID
What would you have to do to tie those together?