i have three tables
customer
id | name
1 | john
orders
id | customer_id | date
1 | 1 | 2013-01-01
2 | 1 | 2013-02-01
3 | 2 | 2013-03-01
order_details
id | order_id | qty | cost
1 | 1 | 2 | 10
2 | 1 | 5 | 10
3 | 2 | 2 | 10
4 | 2 | 2 | 15
5 | 3 | 3 | 15
6 | 3 | 3 | 15
i need to select data so i can get the output for each order_id the summary of the order
sample output. I will query the database with a specific customer id
output
date | amount | qty | order_id
2013-01-01 | 70 | 7 | 1
2013-02-01 | 50 | 4 | 2
this is what i tried
SELECT
orders.id, orders.date,
SUM(order_details.qty * order_details.cost) AS amount,
SUM(order_details.qty) AS qty
FROM orders
LEFT OUTER JOIN order_details ON order_details.order_id=orders.id AND orders.customer_id = 1
GROUP BY orders.date
but this returns the same rows for all customers, only that the qty and cost dont hav values
Maybe
SELECT
orders.id, orders.date,
SUM(order_details.qty * order_details.cost) AS amount,
SUM(order_details.qty) AS qty
FROM orders
LEFT JOIN order_details ON order_details.order_id=orders.id
AND orders.customer_id = 1
GROUP BY orders.date
HAVING amount is not null AND qty is not null
SQL Fiddle
NOTE: In the following query, it is assumed that the dates are stored in the database as a string in the format specified in the OP. If they are actually stored as some type of date with time then you'll want to modify this query such that the time is truncated from the date so the date represents the whole day. You can use the date or date_format functions. But then you'll need to make sure that you modify the query appropriately so the group by and select clauses still work. I added this modification as comments inside the query.
select
o.date -- or date(o.date) as date
, sum(odtc.total_cost) as amount
, sum(odtc.qty) as qty
, o.order_id
from
orders o
inner join (
select
od.id
, od.order_id
, od.qty
, od.qty * od.cost as total_cost
from
order_details od
inner join orders _o on _o.id = od.order_id
where
_o.customer_id = :customer_id
group by
od.id
, od.order_id
, od.qty
, od.cost
) odtc on odtc.order_id = o.id
where
o.customer_id = :customer_id
group by
o.date -- or date(o.date)
, o.order_id
;
I don't think you want an outer join just a simple inner join on all 3 tables:
FROM orders, order_details, customer
WHERE orders.customer_id=customer.id
AND order_details.order_id=orders.id
Related
I have two tables: invoices and items.
invoices
id | timest
items
id | invoice_id | price | qty
It is apparent an invoice may have several items - items.invoice_id = invoices.id.
I have the following query that selects all invoices with the total sum of theirs items:
SELECT id, DATE_FORMAT(FROM_UNIXTIME(inv.time), "%Y-%m" ) AS _period,
(SELECT SUM(it.price*it.quantity) FROM items AS it WHERE it.invoice_id=inv.id) as total
FROM `invoices` `inv`
This generates something like:
id| _period | total
-------------------
1 | 2014-06 | 100
4 | 2014-06 | 200
5 | 2014-07 | 660
6 | 2014-07 | 300
7 | 2014-07 | 30
9 | 2015-02 | 225
Now I want to group it by the period to have output as:
_period | qty | total_price
---------------------------
2014-06 | 2 | 300
2014-07 | 3 | 990
2015-02 | 1 | 224
I can easily do it for the quantity field as
SELECT DATE_FORMAT(FROM_UNIXTIME(inv.time), "%Y-%m" ) AS _period,
COUNT(inv.id) as qty
FROM `invoices` `inv`
GROUP BY _period
But I can't figure out how the similar thing could be done for the total_price field, which results from a subquery virtual field? Does anyone have any idea?
Thank you!
You should do this using a LEFT JOIN and GROUP BY:
SELECT DATE_FORMAT(FROM_UNIXTIME(i.time, '%Y-%m') AS _period,
COUNT(DISTINCT i.id) as num_invoices
SUM(i.price * it.quantity) as total
FROM invoices i LEFT JOIN
items it
ON it.invoice_id = i.id
GROUP BY _period
ORDER BY _period;
try this
SELECT InnerTable._period, Count(InnerTable.id) as id, Sum(InnerTable.total) as total FROM
(SELECT id, DATE_FORMAT(FROM_UNIXTIME(inv.time), "%Y-%m" ) AS _period,
(SELECT SUM(it.price*it.quantity) FROM items AS it WHERE it.invoice_id=inv.id) as total
FROM `invoices` `inv`) as InnerTable FROM GROUP BY InnerTable._period.
Making sub table from the query and then put group by on it.
I need to get all the details from the orders table, with the latest status ID in the orders statuses table, and then the name of that status from the states table.
orders
id | customer | product
-----------------------
1 | David | Cardboard Box
Order_to_statuses
id | order | status | updated_at
--------------------------------
1 | 1 | 1 | 2017-05-30 00:00:00
2 | 1 | 3 | 2017-05-28 00:00:00
3 | 1 | 4 | 2017-05-29 00:00:00
4 | 1 | 2 | 2017-05-26 00:00:00
5 | 1 | 5 | 2017-05-05 00:00:00
order_states
id | name
---------
1 | Pending
2 | Paid
3 | Shipped
4 | Refunded
In this instance, I would need to get the customer and product, with the latest status ID from the order statuses table, and then the name of that state.
How can I do this?
I'd break this down by first getting the max(updated_at) for each order, then work to everything else you need. You can get the max date for each order by using subquery:
select
s.`order`,
s.`status`,
s.updated_at
from order_to_statuses s
inner join
(
select
`order`,
max(updated_at) as updated_at
from order_to_statuses
group by `order`
) m
on s.`order` = m.`order`
and s.updated_at = m.updated_at
Once you get this you now have the order, the status id, and the most recent date. Using this you can then JOIN to the other tables, making your full query:
select
o.customer,
o.product,
ots.updated_at,
os.name
from orders o
inner join
(
select
s.`order`,
s.`status`,
s.updated_at
from order_to_statuses s
inner join
(
select
`order`,
max(updated_at) as updated_at
from order_to_statuses
group by `order`
) m
on s.`order` = m.`order`
and s.updated_at = m.updated_at
) ots
on o.Id = ots.`order`
inner join order_states os
on ots.`status` = os.id;
See a demo
It may have some typo, but the idea of the query should be something like this:
select orders.id, orders.customer, orders.product,
order_to_status.status, staus.name
from orders, order_to_status, status
where orders.id = order_to_status.order
and order_to_status.status = status.id
and order_to_status.updated_at in (
SELECT MAX(order_to_status.updated_at)
FROM order_to_status
where order_to_status.order = orders.id
group by order_to_status.order
);
I ussually don't use joins but with joins it should be like this:
select orders.id, orders.customer, orders.product,
order_to_status.status, staus.name
from orders
JOIN order_to_status ON orders.id = order_to_status.order
JOIN status ON order_to_status.status = status.id
where
order_to_status.updated_at in (
SELECT MAX(order_to_status.updated_at)
FROM order_to_status
where order_to_status.order = orders.id
group by order_to_status.order
);
Note I added a group by I had missed.
EDIT 2
I had an error in the subquery condition.
changed to where order_to_status.order = orders.id
also moved the group by after the where clause.
I have two table amount_to_pay and paid_amount in amount_to_pay table data inserted as per center_id and university_id for which center for which university how much amount he has to pay and in paid_amount data inserted as which center for which university how much amount he paid, I want net amount pending from center for particular university as shown in third table below.
This is first table amount_to_pay
+---------+--------------+-------------+
|center_id|university_id |amount_topay |
+---------+--------------+-------------+
| 1 | 6 |29000 |
+---------+--------------+-------------+
| 1 | 7 |19700 |
+---------+--------------+-------------+
| 2 | 6 |9000 |
+---------+--------------+-------------+
This is my second table paid_amount
+---------+--------------+------------+
|center_id|university_id |amount_paid |
+---------+--------------+------------+
| 1 | 6 |9000 |
+---------+--------------+------------+
| 2 | 6 |5000 |
+---------+--------------+------------+
And want output as Below table
+---------+--------------+-------+
|center_id|university_id |amount |
+---------+--------------+-------+
| 1 | 6 |20000 |
+---------+--------------+-------+
| 1 | 7 |19700 |
+---------+--------------+-------+
| 2 | 6 |4000 |
+---------+--------------+-------+
Above amount_topay column is sum of amount_topay and group by center_id and university_id
In second table also amount_paid is sum of amount_paid column and group by center_id and university_id.
You could join the tables and subtract the amounts. Note that you should use a left join so you don't miss entries where no payments have been made yet:
SELECT a.center_id,
a.university_id,
a.amount_to_pay - COALESCE(p.amount_paid, 0) AS amount
FROM amount_to_pay a
LEFT JOIN paid_amount p ON a.center_id = p.center_id AND
a.university_id = p.university_id
You could use a join and agroup by
select
a.center_id
, a.university_id
, sum(a.amount_topay) - sum(ifnull(b.amount_paid,0) as amount
from amount_to_pay as a
left join paid_amount as b
on a.center_id = b.center_id
and a.university_id = b.university_id
group by a.center_id, a.university_id
try this
SELECT p1.center_id,p1.university_id,p1.amount_topay,p2.amount_paid,
CASE WHEN p1.center_id = p2.center_id AND p1.university_id = p2.university_id then amount_topay - amount_paid
WHEN p1.center_id <> p2.center_id and p1.university_id <> p2.university_id then amount_topay
END as total
FROM amount_to_pay p1
LEFT JOIN paid_amount p2
ON amount_topay > amount_paid
GROUP BY total HAVING total is not null
ORDER BY total desc;
see demo
Try this simple one & Make sure you have applied unique key for center_id and university_id combination
SELECT
a.center_id
, a.university_id
, SUM(a.amount_topay)- SUM(inull(b.amount_paid,0) AS amount
FROM amount_to_pay AS a
LEFT OUTER JOIN paid_amount AS b
ON(a.center_id = b.center_id
AND a.university_id = b.university_id)
GROUP BY a.center_id, a.university_id
I need to join together 2 SQL statements and both of those statements work on their own. But I don't know how to combine both into 1 SQL statement.
I have two tables in 1st statement, TR120 and TR1201.
The SQL is this:
select
PRODUCT, PRICE, QUANTITY, INVOICE.DATE
from
TR1201
left join
(select
DATE, ID as INVOICE_ID, INVOICE
from TR120) as INVOICE on INVOICE.INVOICE_ID = ID
where
INVOICE.DATE >= '2016-06-01' and INVOICE.DATE <= '2016-06-30'
This returns a list of all the products I sold, with price, quantity and date of sales in a specific time frame from 01-06-16 till 30-06-16.
Now I need to find out the latest price that I bought product for in different two tables TR100 and TR1001 based on the product and date of sale from the 1st SQL statement.
select
PRODUCT, PRICE, SUP.DATE
from
TR1001
left join
(select
DATE, ID as SUP_ID, SUP_INVOICE
from TR100) as SUP on SUP.SUP_ID = ID
This returns a list of all the products that I have bought with a price and a date. I only need last record from this query based on product and date of purchased.
TR120
ID | INVOICE | DATE
1 | 000001 |2016-06-05
2 | 000002 |2016-06-15
3 | 000003 |2016-06-25
TR1201
ID | PRODUCT | PRICE A | QUANTITY
1 | A | 2,00 | 5
2 | A | 2,00 | 2
3 | A | 2,00 | 1
TR100
ID | SUP_INVOICE | DATE
1 | 160001 | 2016-05-30
2 | 160002 | 2016-06-16
TR1001
ID | PRODUCT | PRICE B
1 | A | 0,5
2 | A | 0,7
The result I am trying to get is this:
PRODUCT | PRICE A (tr1201) | QUANTITY | DATE (tr100) | PRICE B (tr1001)
A | 2 | 5 | 2016-05-30 | 0,5
A | 2 | 2 | 2016-05-15 | 0,5
A | 2 | 1 | 2016-05-16 | 0,7
That is all I want to do :(
Have you tried first_value?
FIRST_VALUE ( [scalar_expression ] )
OVER ( [ partition_by_clause ] order_by_clause [ rows_range_clause ] )
it works like this:
select distinct id,
first_value(price) over (partition by id (,sup) order by date DESC (latest, ASC for oldest)) as last_price
from table;
Documentation can be found here: https://msdn.microsoft.com/en-us/library/hh213018.aspx
I don't have your tables so cannot test and therefore am providing advice only.
I think what you need is an Outer apply like this instead of joins
select
T1.Product
, T1.Price
, T2.DATE -- Alias this
, T2.Price -- Alias this
, T3.DATE -- Alias this
, T3.Price -- Alias this
from T1
OUTER APPLY (
select top 1
Date
,Price
from table2
WHERE ID = T1.Id AND product = T1.Product-- plus any other joins
ORDER BY Date desc
) as T2
OUTER APPLY (
select top 1
Date
,Price
from table3
WHERE ID = T1.Id AND product = T1.Product-- plus any other joins
ORDER BY Date desc
) as T3
I have orders table, order_details table
I join orders table with order_details table to make a temporary table that look like this
order_id | customer_id | Quantity |
2 | 2 | 10 |
2 | 2 | 25 |
2 | 2 | 5 |
2 | 2 | 15 |
3 | 2 | 25 |
What I am trying to achieve is sum Quantity column where order_id is same.
so the end result look like this
order_id | customer_id | Quantity |
2 | 2 | 55 |
3 | 2 | 25 |
my sql statement to get to here look like this
SELECT
orders.orders_id,
orders.customer_id_fk,
sum(order_detail.quantity)
FROM orders
LEFT JOIN order_detail on orders.orders_id = order_detail.orders_id_fk
WHERE customer_id_fk IN(2) <-- this is needed because I only want to see customer 2.
how do I put a condition on the sum ?
Looks like you are very close!
You should be able to group by order_idto get a list of unique order_ids with the Quantity sum for each order_id
SELECT
orders.orders_id,
orders.customer_id_fk,
sum(order_detail.quantity)
FROM orders
LEFT JOIN order_detail on orders.orders_id = order_detail.orders_id_fk
WHERE customer_id_fk IN(2)
GROUP BY orders.orders_id,orders.customer_id_fk
use Group by
SELECT
orders.orders_id,
orders.customer_id_fk,
sum(order_detail.quantity)
FROM orders
LEFT JOIN order_detail on orders.orders_id = order_detail.orders_id_fk
WHERE customer_id_fk IN(2) GROUP BY orders.orders_id,orders.customer_id_fk
Here is OP. Sorry I derped. I put GROUP BY after Order by and it didnt work. the below sovled it
SELECT
orders.orders_id,
orders.customer_id_fk,
sum(order_detail.quantity)
FROM orders
LEFT JOIN order_detail on orders.orders_id = order_detail.orders_id_fk
WHERE customer_id_fk IN(2)
GROUP BY orders_id
ORDER BY customer_id