Difference between dates with one date column in mysql - mysql

i have the below query:
SELECT transaction_date,tanks.name,stations.name,products.name,tank_sales
FROM tanks_product_movement LEFT JOIN stations ON station_id=stations.id
LEFT JOIN products ON product_id=products.id LEFT JOIN tanks ON
tank_id=tanks.id WHERE products.name='AGO'
AND stations.name='CG-Station'
i want to know the difference in sales between two days i.e sales difference between 2019-04-01 and 2019-04-02 ?
enter image description here

Assuming these two dates would occur only once in the respective table, you could use pivoting logic here:
SELECT
MAX(CASE WHEN transaction_date = '2019-04-02' THEN tank_sales END) -
MAX(CASE WHEN transaction_date = '2019-04-01' THEN tank_sales END) AS sales_diff
FROM tanks_product_movement tpm
LEFT JOIN stations s
ON tpm.station_id = s.id
LEFT JOIN products p
ON tpm.products_id = p.id
LEFT JOIN tanks t
ON tank_id = t.id
WHERE
p.name = 'AGO' AND
s.name = 'CG-Station';
To find the difference between today and yesterday's sales use:
SELECT
MAX(CASE WHEN transaction_date = CURDATE() THEN tank_sales END) -
MAX(CASE WHEN transaction_date = SUBDATE(CURDATE(), 1) THEN tank_sales END)

Related

LEFT JOIN with multiple nested select

The following statement surprisingly works, but I'm not sure joining the same table 3 times is efficient. I had to disable ONLY_FULL_GROUP_BY in order for it to work.
There are 2 tables in play. One is the main table with Distributor information, the second is a table of purchases that contains the amount, date, and id of the associated Distributor in the main table (assoc).
There are 3 things I needed. Year to date sales, which SUMS the amount of a certain Distributor's sales from the current year. Last year sales, which does the same for the previous year. Then finally just get the latest purchase date and amount.
The user needs to be able to filter by these values (lys, ytd, etc...) so joining them as variables seems like the way to go. The DB size is about 7,000 records.
SELECT
d.*,
ytd_total,
lys_total,
last_amount,
last_purchase
FROM Distributor as d
LEFT JOIN (
SELECT
assoc, SUM(amount) ytd_total
FROM purchases
WHERE db = 1 AND purchase_date >= '{$year}-01-01'
GROUP BY assoc
) AS ytd
ON ytd.assoc = d.id
LEFT JOIN (
SELECT
assoc, SUM(amount) lys_total
FROM purchases
WHERE db = 1 AND purchase_date BETWEEN '{$lyear}-01-01' AND '{$lyear}-12-31'
GROUP BY assoc
) AS lys
ON lys.assoc = d.id
LEFT JOIN (
SELECT
assoc, amount last_amount, purchase_date last_purchase
FROM purchases
WHERE db = 1
GROUP BY assoc
) AS lst
ON lst.assoc = d.id
WHERE ........
You can do more work in each aggregation query. I think this is more whatyou want:
select d.*, pa.ytd_total, pa.lys_total, pa.last_purchase_date, p.amount
from distributor d left join
(select p.assoc,
sum(case when p.purchase_date >= '{$year}-01-01' then p.amount end) as ytd_total,
sum(case when p.purchase_date BETWEEN '{$lyear}-01-01' AND '{$lyear}-12-31' then p.amount end) as lys_total,
max(p.purchase_date) as last_purchase_date
from purchases p
where p.db = 1
group by p.assoc
) pa left join
purchases p
on pa.assoc = p.assoc and pa.last_purchase_date = p.purchase_date;

MySQL subquery in select

I have the following scenario. i have three tables (users, sales, sales_details) Users to Sales is a 1 to 1 relationship and sales to sales_details is 1 to many.
I am running a query where I get all the sales for each user by joining all 3 tables without any issue.
Query looks something like this
SELECT s.month as month,u.name as name, s.year as year, s.date as date,sum(sd.qty) as qty,sum(sd.qty*sd.value) as value,s.id as id,sum(sd.stock) as stock,s.currency as currency,s.user as user
FROM sales as s
left join sales_details as sd on s.id = sd.Sales
inner join users as u on s.user = u.Id
group by s.Id
What I want to do now is add an extra field in my query which will be a subquery.
SELECT SUM(total) AS total_yearly
FROM (
SELECT sum(qty) as total
FROM sales
left join sales_details on sales.Id = sales_details.Sales
WHERE ((month <= MONTH(NOW()) and year = YEAR(NOW()))
or (month >= MONTH(Date_add(Now(),interval - 12 month)) and year = YEAR(Date_add(Now(),interval - 12 month))))
and User = **ID OF USER** ) as sub
This query on its own gives me the sales for the user for the past 12 months while the original query does it per month. I know that the result will be the same for each user but i need it for other calculations.
My problem is how I will join the 2 queries so that the subquery will read the user id from the original one.
Thanks in advance!
Group the second query by user, and then join it with the original query.
SELECT s.month as month,u.name as name, s.year as year, s.date as date,
sum(sd.qty) as qty,sum(sd.qty*sd.value) as value,s.id as id,
sum(sd.stock) as stock,s.currency as currency,s.user as user,
us.total
FROM sales as s
left join sales_details as sd on s.id = sd.Sales
inner join users as u on s.user = u.Id
inner join (
SELECT User, sum(qty) as total
FROM sales
left join sales_details on sales.Id = sales_details.Sales
WHERE ((month <= MONTH(NOW()) and year = YEAR(NOW()))
or (month >= MONTH(Date_add(Now(),interval - 12 month)) and year = YEAR(Date_add(Now(),interval - 12 month)))))
GROUP BY User) AS us ON s.user = us.user
group by s.Id

COUNT total of group by mysql

This mysql query gives me the number of sales of my products (total and total_staff) grouped by days and hours of the day. I want the sum of total and total_staff for each product (not grouped by anything, expect by id). Can I do this in the same query?
SELECT p.name, p.color, DATE(date_create) as jour,HOUR(date_create) AS h,
SUM(CASE WHEN s.staff=0 THEN 1 ELSE 0 END) as total,
SUM(CASE WHEN s.staff=1 THEN 1 ELSE 0 END) as total_staff
FROM manifsSubCategories msc
LEFT JOIN products_subCategories psc ON msc.id=psc.manifSubCategory_id
LEFT JOIN sales s ON psc.product_id=s.product_id
LEFT JOIN products p ON psc.product_id=p.id
LEFT JOIN manifsCategories ON manifCategory_id=manifsCategories.id
WHERE manifCategory_id=1 AND s.category_id=1 GROUP BY jour,h ORDER BY p.id DESC
Just omit the other columns :
SELECT p.name,
SUM(CASE WHEN s.staff=0 THEN 1 ELSE 0 END) as total,
SUM(CASE WHEN s.staff=1 THEN 1 ELSE 0 END) as total_staff
FROM manifsSubCategories msc
LEFT JOIN products_subCategories psc ON msc.id=psc.manifSubCategory_id
LEFT JOIN sales s ON psc.product_id=s.product_id
LEFT JOIN products p ON psc.product_id=p.id
LEFT JOIN manifsCategories ON manifCategory_id=manifsCategories.id
WHERE manifCategory_id=1 AND s.category_id=1
GROUP BY p.name
ORDER BY p.id DESC
BTW - Your WHERE clause is wrong. You are filtering by a table for the LEFT JOIN , this will turn your join into an inner join due to NULL comparison. Conditions on the right table of a left join should only be placed inside the ON clause.

SQL Query count how many products bought on one day by those who bought more than 3 products on a different day

I want to write a query to count how many chairs were bought on 2015-01-01 by those who bought 2 or more of any products on 2016-01-01
Tables:
Sales (date, customer_id, product_id, units_sold)
Products (id, name, price)
Customers (id, name)
My SQL code so far:
SELECT sum(s.units_sold)
FROM Sales s, Products p
WHERE p.name = 'Chair' and s.date = '2015-01-01' and s.product_id = p.id;
Fiddle: http://sqlfiddle.com/#!9/a0b56
Not very efficient, but produces the desired results
SELECT sum(s.units_sold)
FROM Sales s, Products p
WHERE p.name = 'Chair' and s.date = '2015-01-01' and s.product_id = p.id
AND s.customer_id IN (SELECT customer_id FROM Sales WHERE date = '2016-01-01' AND units_sold > 1)
One method is to use two levels of aggregation, the first at the customer level and the second overall:
SELECT SUM(chairs_2015)
FROM (SELECT s.customer_id,
SUM(CASE WHEN p.name = 'Chair' and s.date = '2015-01-01
THEN s.units_sold
END) as chairs_2015,
FROM Sales s JOIN
Products p
ON s.product_id = p.id
WHERE SUM(CASE WHEN s.date = '2016-01-01 THEN 1 ELSE 0 END) >= 2
GROUP BY s.customer_id
) s;

SQL Query Help for Chart Data

Here is our goal:
We want to select each month and the revenue gained for each month, for a particular user.
Here are our tables
product, purchase, user, months
user 1..* product, product 1..* purchase
product has a column 'user_id' and purchase has a column 'product_id'
months is just a table that contains each month as a string. Currently, we are using this to do some left joins as you can see below.
SELECT months.name, IFNULL(sum(purchase.price), 0) as revenue
FROM months
LEFT JOIN purchase
ON DATE_FORMAT(purchase.purchase_date, '%M') = months.name
AND DATE_FORMAT(purchase_date, '%Y') = DATE_FORMAT(CURRENT_DATE, '%Y')
AND purchase.status = 2
GROUP BY name
ORDER BY months.id ASC;
Which works great for ALL of the users and ALL of the purchases made this month (Purchase status of 2 means complete). The next part is how do I filter this based on a user id? The table 'product' has the user_id we're looking for, and table purchase has a 'product_id'. Everytime I try something it either does nothing or it removes all of the null values, which we don't want.
ATTEMPT #NathanialWools
The where clause will remove all of the rows with a revenue of zero (or null, because of the IFNULL statement). This is what I tried:
SELECT name, IFNULL(sum(purchase.price), 0) as revenue
FROM months
LEFT JOIN purchase
ON DATE_FORMAT(purchase.purchase_date, '%M') = months.name
AND DATE_FORMAT(purchase_date, '%Y') = DATE_FORMAT(CURRENT_DATE, '%Y')
AND purchase.status = 2
LEFT JOIN product
ON product.id = purchase.product_id
WHERE product.user_id = 1
GROUP BY name
ORDER BY months.id ASC;
If you have a list of users you could start with that, join to months, then join to product. (if you don't just start with product).
SELECT u.user_id, m.name, IFNULL(sum(p.price), 0) as revenue
FROM user u
CROSS JOIN months m
LEFT JOIN product d
ON u.user_id = d.user_id
LEFT JOIN purchase p
ON DATE_FORMAT(p.purchase_date, '%M') = m.name
AND DATE_FORMAT(p.purchase_date, '%Y') = DATE_FORMAT(CURRENT_DATE, '%Y')
AND p.product_id = d.product_id
AND p.status = 2
WHERE u.user_id = <user you care about>
GROUP BY u.user_id, m.name
ORDER BY m.id ASC;
LEFT JOIN on product, and add a WHERE clause where user_id is null or user_id is equal to your value.
What did you try?
SELECT months.name, u.user_id, sum(IFNULL(purchase.price, 0)) as revenue
FROM months
LEFT JOIN purchase pu
ON DATE_FORMAT(purchase.purchase_date, '%M') = months.name
AND DATE_FORMAT(purchase_date, '%Y') = DATE_FORMAT(CURRENT_DATE, '%Y')
AND purchase.status = 2
LEFT JOIN product pr
ON pr.product_id = pr.product_id
LEFT JOIN user u
ON u.user_id = pr.user_id
GROUP BY pu.name, u.user_id
ORDER BY months.id ASC;
An inner-select Seems to do the trick. The left join on the purchase alone was not enough filtering. Here is the solution that works for me:
SELECT m.name, IFNULL(sum(b.price), 0) as revenue
FROM months as m
LEFT JOIN (SELECT price, purchase_date, status
FROM purchase, product
WHERE purchase.product_id = product.id
AND product.user_id = 1) as b
ON DATE_FORMAT(b.purchase_date, '%M') = m.name
AND DATE_FORMAT(b.purchase_date, '%Y') = DATE_FORMAT(CURRENT_TIMESTAMP, '%Y')
AND status = 2
GROUP BY m.name
ORDER BY m.id ASC
Where you would obviously change the '1' based on which user you wanted to look at.
Thanks everyone for pitching in, made debugging faster.