I have daily data for multiple locations that we need to compare last week total sales with total sales 2 weeks ago. Here is the MYSQL code
SELECT
name,
SUM(CASE WHEN WEEK(date) = WEEK(now())-1 THEN sales ELSE NULL END) as 'Last Week',
SUM(CASE WHEN WEEK(date) = WEEK(now())-2 THEN sales ELSE NULL END) as '2 Weeks Ago',
SUM('1week' - '2week') AS 'Change'
FROM daily_sales
GROUP BY name
The output for the 1st three columns is correct, but I cannot get the 4th column "change" to calculate correctly. Tried SUM of the cases but could not get over invalid use og group function:
SUM((SUM(CASE WHEN WEEK(date) = WEEK(now())-1 THEN sales ELSE NULL END))
- (SUM(CASE WHEN WEEK(date) = WEEK(now())-2 THEN sales ELSE NULL END))) AS 'change'
Help!
You're almost there; just take the formula that give cols 2 and 3 and put a minus between them:
SELECT
name,
SUM(CASE WHEN WEEK(date) = WEEK(now())-1 THEN sales END) as LastWeek,
SUM(CASE WHEN WEEK(date) = WEEK(now())-2 THEN sales END) as TwoWeeksAgo,
SUM(CASE WHEN WEEK(date) = WEEK(now())-1 THEN sales END) - SUM(CASE WHEN WEEK(date) = WEEK(now())-2 THEN sales END) as change
FROM daily_sales
WHERE date >= date_sub(now(), interval 3 week)
GROUP BY name
Or by use of a subquery:
SELECT name, lastweek, twoweeksago, lastweek - twoweeksago as change
FROM
(
SELECT
name,
SUM(CASE WHEN WEEK(date) = WEEK(now())-1 THEN sales END) as LastWeek,
SUM(CASE WHEN WEEK(date) = WEEK(now())-2 THEN sales END) as TwoWeeksAgo
FROM daily_sales
WHERE date >= date_sub(now(), interval 3 week)
GROUP BY name
) x
Or by use of a cte:
WITH x AS(
SELECT
name,
SUM(CASE WHEN WEEK(date) = WEEK(now())-1 THEN sales END) as LastWeek,
SUM(CASE WHEN WEEK(date) = WEEK(now())-2 THEN sales END) as TwoWeeksAgo
FROM daily_sales
WHERE date >= date_sub(now(), interval 3 week)
GROUP BY name
)
SELECT name, lastweek, twoweeksago, lastweek - twoweeksago as change
Related
I want to calculate 2 sum() i have tried query as below it works but very slowly. Any ideas to make it better?
SELECT customer,
SUM(CASE WHEN book_day BETWEEN '2020-01-01' AND '2020-01-31'
THEN pax+free
ELSE 0
END) AS January,
SUM(CASE WHEN book_day BETWEEN '2020-02-01' AND '2020-02-31'
THEN pax+free
ELSE 0
END) AS February,
( SUM(CASE WHEN book_day BETWEEN '2020-01-01' AND '2020-01-31'
THEN pax+free
ELSE 0
END) +
SUM(CASE WHEN book_day BETWEEN '2020-02-01' AND '2020-02-31'
THEN pax+free
ELSE 0
END) ) AS total
FROM rezervations
How can i make simplier like January + February as total
keep BETWEEN '2020-01-01' AND '2020-02-29' in where clause.
make sure there is index on book_day column
SELECT customer,
SUM(CASE WHEN book_day BETWEEN '2020-01-01' AND '2020-01-31' THEN pax+free ELSE 0 END) as January,
SUM(CASE WHEN book_day BETWEEN '2020-02-01' AND '2020-02-29' THEN pax+free ELSE 0 END) as February,
(SUM(CASE WHEN book_day BETWEEN '2020-01-01' AND '2020-02-29' THEN pax+free ELSE 0 END) ) as total
FROM rezervations
WHERE
book_day BETWEEN '2020-01-01' AND '2020-02-29'
I have table:
User nvarchar(30)
Date datetime
Total decimal(8,2)
And i need to get data per month like this:
I can get it this way (without month columns):
SELECT User, MONTHNAME(FROM_UNIXTIME(Date)) as month, SUM(Total) as total FROM `wp_banking_expenses` group by month,User
But i need it to make as on image above...
You can try to use condition aggregate function.
SELECT User,
SUM(CASE WHEN MONTHNAME(Date) = 'January' THEN Total END) as Jan,
SUM(CASE WHEN MONTHNAME(Date) = 'February' THEN Total END) as Feb,
SUM(CASE WHEN MONTHNAME(Date) = 'March' THEN Total END) as Mar,
SUM(CASE WHEN MONTHNAME(Date) = 'April' THEN Total END) as Apr,
SUM(CASE WHEN MONTHNAME(Date) = 'May' THEN Total END) as May,
SUM(CASE WHEN MONTHNAME(Date) = 'June' THEN Total END) as JUN,
SUM(CASE WHEN MONTHNAME(Date) = 'July' THEN Total END) as JUL,
SUM(CASE WHEN MONTHNAME(Date) = 'August' THEN Total END) as AUG,
SUM(CASE WHEN MONTHNAME(Date) = 'September' THEN Total END) as SEP,
SUM(CASE WHEN MONTHNAME(Date) = 'October' THEN Total END) as OCT,
SUM(CASE WHEN MONTHNAME(Date) = 'November' THEN Total END) as NOV,
SUM(CASE WHEN MONTHNAME(Date) = 'December' THEN Total END) as DEC
FROM `wp_banking_expenses`
group by User
use conditional aggregation using case when expression
select user,max(case when month='January' then total end) as Jan,
max(case when month='February' then total end) as Feb,
max(case when month='March' then total end) as Mar,
max(case when month='April' then total end) as Apr,
max(case when month='May' then total end) as May,
max(case when month='June' then total end) as June,
----
from
(
SELECT User, MONTHNAME(Date) as month, SUM(Total) as total
FROM `wp_banking_expenses`
group by month,User
)A group by user
I have sales table and have two different date ranges.
i.e, I have total sales between (2016-12-21 - 2016-12-30) is 100 and for period (2016-12-11 - 2016-12-20) is 85.
Now the result I want is
100 (sales of 2016-12-21 - 2016-12-30), 85 (sales of 2016-12-11 - 2016-12-20), 15 (difference of both periods) through single query.
What I am thinking is
select *, (a.sales - b.sales) as diff
from (select id, sum(sales) as sales from salestable where date >= '2016-12-21' and date <= '2016-12-30') a
join (select id, sum(sales) as sales from salestable where date >= '2016-12-11' and date <= '2016-12-20') b
on a.id = b.id;
Is there any other better way to do this?
You can use conditional aggregation:
select sum(case when date >= '2016-12-21' and date <= '2016-12-30' then sales else 0
end) as sales_a,
sum(case when date >= '2016-12-11' and date <= '2016-12-20' then sales else 0
end) as sales_b,
sum(case when date >= '2016-12-21' and date <= '2016-12-30'
then sales else 0
when date >= '2016-12-11' and date <= '2016-12-20'
then -sales
else 0
end) as sales_diff
from salestable;
If you want the overall sum by id (as suggested by your inclusion of id), then add id to the select and add group by id.
You can use case to do a conditional sum like this:
select id,
sum_21_to_30,
sum_11_to_20,
sum_21_to_30 - sum_11_to_20 diff
from (select id,
sum(case when date >= '2016-12-21' and date <= '2016-12-30' then sales else 0 end) sum_21_to_30,
sum(case when date >= '2016-12-11' and date <= '2016-12-20' then sales else 0 end) sum_11_to_20
from table group by id) t;
Hello I am trying to get records of certain months. For example for this query I would want the user to see the current month which is "May" and one month from the past which would be "April". I don't want my query to run any other month from that point on. I am stuck with this query and cant figure it out. Basically I need a function in my query to automatically know this month and the 1 month before to show the records. Thank you
DECLARE #Year int
set #Year = 2014
SELECT d.name, a.dealer_code, b.last_name, b.city, b.state, b.phone
, COUNT(CASE WHEN MONTH(c.Funded_date) = 1 THEN 1 ELSE NULL END) January
, COUNT(CASE WHEN MONTH(c.Funded_date) = 2 THEN 1 ELSE NULL END) Feburary
, COUNT(CASE WHEN MONTH(c.Funded_date) = 3 THEN 1 ELSE NULL END) March
, COUNT(CASE WHEN MONTH(c.Funded_date) = 4 THEN 1 ELSE NULL END) April
, COUNT(CASE WHEN MONTH(c.Funded_date) = 5 THEN 1 ELSE NULL END) May
, COUNT(CASE WHEN MONTH(c.Funded_date) = 6 THEN 1 ELSE NULL END) June
, COUNT(CASE WHEN MONTH(c.Funded_date) = 7 THEN 1 ELSE NULL END) July
, COUNT(CASE WHEN MONTH(c.Funded_date) = 8 THEN 1 ELSE NULL END) August
, COUNT(CASE WHEN MONTH(c.Funded_date) = 9 THEN 1 ELSE NULL END) September
, COUNT(CASE WHEN MONTH(c.Funded_date) = 10 THEN 1 ELSE NULL END) October
, COUNT(CASE WHEN MONTH(c.Funded_date) = 11 THEN 1 ELSE NULL END) November
, COUNT(CASE WHEN MONTH(c.Funded_date) = 12 THEN 1 ELSE NULL END) December
, COUNT(*) 'Year to Date'
FROM tdealer a
JOIN tContact b ON a.contact_id = b.contact_id
JOIN tContract c ON a.dealer_id = c.dealer_id
JOIN tCompany d ON c.company_id = d.company_id
where YEAR (c.Funded_date) = #Year
GROUP BY d.name, a.dealer_code, b.last_name, b.city, b.state, b.phone
The trick here is to do two things:
Create an expression which converts any arbitrary DATETIME into the first day of the month in which that date occurred.
Use it appropriately in WHERE and GROUP BY clauses.
The expression is
DATE_FORMAT(whatever, '%Y-%m-01')
This takes, for example '2014-05-28 12:22:30', and turns it into '2014-05-01'. It's really handy to convert one valid DATE to another valid DATE, because then you can use all the good date arithmetic built into MySQL.
So, for example, if you want the first of the month before the present month you use this:
DATE_FORMAT(NOW(), '%Y-%m-01') - INTERVAL 1 MONTH
Here's the outline of your query:
SELECT DATE_FORMAT(c.Funded_date, '%Y-%m-01') AS month_beginning,
d.name, a.dealer_code, b.last_name, b.city, b.state, b.phone,
COUNT(1) AS itemcount
FROM tdealer a
JOIN tContact b ON a.contact_id = b.contact_id
JOIN tContract c ON a.dealer_id = c.dealer_id
JOIN tCompany d ON c.company_id = d.company_id
where c.Funded_date >= DATE_FORMAT(NOW(), '%Y-%m-01') - INTERVAL 1 MONTH
AND c.Funded_date < DATE_FORMAT(NOW(), '%Y-%m-01') + INTERVAL 1 MONTH
GROUP BY DATE_FORMAT(c.Funded_date, '%Y-%m-01'),
d.name, a.dealer_code, b.last_name, b.city, b.state, b.phone
ORDER BY d.name, a.dealer_code, b.last_name, b.city, b.state, b.phone,
DATE_FORMAT(c.Funded_date, '%Y-%m-01')
See how you choose the two-month period? It starts with the first day of the month before the present month, and ends with the first day of next month, but without including that day.
How to do this sort of thing is written up at http://www.plumislandmedia.net/mysql/sql-reporting-time-intervals/
I have the following query in oracle so dont know how to convert into SQL Server.
WITH start_date AS
(
SELECT TO_DATE ( '01-Jan-2010'
, 'DD-Mon-YYYY'
) AS start_date
FROM dual
)
SELECT m.task_name
, COUNT (CASE WHEN TO_CHAR (d.task_date, 'DD') = '01' THEN 1 END) AS Day_1
, COUNT (CASE WHEN TO_CHAR (d.task_date, 'DD') = '02' THEN 1 END) AS Day_2
, COUNT (CASE WHEN TO_CHAR (d.task_date, 'DD') = '03' THEN 1 END) AS Day_3
...
, COUNT (CASE WHEN TO_CHAR (d.task_date, 'DD') = '31' THEN 1 END) AS Day_31
FROM task_master m
JOIN task_detail d ON m.task_id = d.task_id
JOIN start_date s ON d.task_date >= s.start_date
AND d.task_date < ADD_MONTHS (s.start_date, 1)
GROUP BY m.task_name
;
Have a look at using
DATEPART to check the day of month (use d or dd)
and
CONVERT(DATETIME,'01-Jan-2010')
for the Date
and
DATEADD to add the date use DATEADD (datepart ,number,date )