i want to count how many values of 1 and 0 i have between 7am and 7am next day.
think here a bar that opens at 10am but closes next day at 7am, they want their 'report' to be for this specific day.
so all data before 7am needs to be added to the day before.
SELECT DATE(delivered), COUNT(*) total,
sum(case when isbag = '0' THEN 1 ELSE 0 END) CloakCount,
sum(case when isbag = '1' THEN 1 ELSE 0 END) BagCount
FROM Wardrobe_CloakTable GROUP BY DATE(delivered)
this will give me almost what i want, the problem is that i need to count all those data before 7am, to the day before.
Something like this should work:
SELECT
CASE WHEN HOUR(delivered) < 7
THEN CONCAT(DATE(DATE_ADD(delivered, INTERVAL -1 day)), ' 07:00:00')
ELSE CONCAT(DATE(delivered), ' 07:00:00')
END as startTime,
CASE WHEN HOUR(delivered) < 7
THEN CONCAT(DATE(delivered), ' 07:00:00')
ELSE CONCAT(DATE(DATE_ADD(delivered, INTERVAL 1 day)), ' 07:00:00')
END as endTime,
COUNT(*) total,
sum(case when isbag = '0' THEN 1 ELSE 0 END) CloakCount,
sum(case when isbag = '1' THEN 1 ELSE 0 END) BagCount
FROM Wardrobe_CloakTable GROUP BY startTime, endTime;
Related
I have the following table in MySQL (Version - 5.7.18-log).
ID Old_Date Curr_Date Status Price items
ID-1 2021-07-14 2021-09-30 13:15:15 Done 1500 3
ID-1 2021-06-26 2021-09-30 13:15:15 Hold 3500 6
ID-1 2021-05-26 2021-09-30 13:15:15 In Progress 4500 1
ID-1 2021-03-04 2021-09-30 13:15:15 Done 5000 3
ID-1 2021-01-11 2021-09-30 13:15:15 Done 2800 2
From the above table, I need to fetch the count & sum of instances where status is Done and Hold in the last 1, 6, and 9-month intervals.
The interval needs to be calculated between Old_Date and Curr_Date.
Required Output-
ID 1_Month_Count 6_Month_Count 9_Month_Count 1_Month_Sum 6_Month_Sum 9_Month_Sum
ID-1 0 2 4 0 5000 12800
I have tried following query but It is not working.
SELECT ID,
SUM(CASE WHEN TIMESTAMPDIFF(month, Old_Date, Curr_Date) <= 12
WHEN (Status IN ('Done', 'Hold') THEN SUM(ID) ELSE 0 END) AS 12_Month_Done`,
FROM Table
Group BY ID;
If you want in the results only the IDs that match your conditions then use conditional aggregation after filtering the table:
SELECT ID,
COUNT(CASE WHEN Old_Date >= Curr_Date - INTERVAL 1 month THEN 1 END) AS `1_Month_Count`,
COUNT(CASE WHEN Old_Date >= Curr_Date - INTERVAL 6 month THEN 1 END) AS `6_Month_Count`,
COUNT(*) AS `9_Month_Count`,
SUM(CASE WHEN Old_Date >= Curr_Date - INTERVAL 1 month THEN Price ELSE 0 END) AS `1_Month_Sum`,
SUM(CASE WHEN Old_Date >= Curr_Date - INTERVAL 6 month THEN Price ELSE 0 END) AS `6_Month_Sum`,
SUM(Price) AS `9_Month_Sum`
FROM tablename
WHERE Status IN ('Done', 'Hold') AND Old_Date >= Curr_Date - INTERVAL 9 month
GROUP BY ID;
If you want all the IDs even if they don't match the conditions:
SELECT ID,
COUNT(CASE WHEN Old_Date >= Curr_Date - INTERVAL 1 month
AND Status IN ('Done', 'Hold') THEN 1 END) AS `1_Month_Count`,
COUNT(CASE WHEN Old_Date >= Curr_Date - INTERVAL 6 month
AND Status IN ('Done', 'Hold') THEN 1 END) AS `6_Month_Count`,
COUNT(CASE WHEN Old_Date >= Curr_Date - INTERVAL 9 month
AND Status IN ('Done', 'Hold') THEN 1 END) AS `9_Month_Count`,
SUM(CASE WHEN Old_Date >= Curr_Date - INTERVAL 1 month
AND Status IN ('Done', 'Hold') THEN Price ELSE 0 END) AS `1_Month_Sum`,
SUM(CASE WHEN Old_Date >= Curr_Date - INTERVAL 6 month
AND Status IN ('Done', 'Hold') THEN Price ELSE 0 END) AS `6_Month_Sum`,
SUM(CASE WHEN Old_Date >= Curr_Date - INTERVAL 9 month
AND Status IN ('Done', 'Hold') THEN Price ELSE 0 END) AS `9_Month_Sum`
FROM tablename
GROUP BY ID;
See the demo.
I think a stored procedure would be a way to achieve this.
In this procedure you will have to do 3 queries for 1, 6 and 9 months.
like
SELECT COUNT(ID) as cnt_id, SUM(price) as sum_price INTO 1_month_count, 1_month_sum WHERE status = 'Hold' OR status = 'Done' AND TIMESTAMPDIFF(MONTH, old_date, curr_date) >= 1 AND TIMESTAMPDIFF(MONTH, old_date, curr_date) < 6;
then you return your variables 1_month_count etc. by
SELECT #1_month_count, #1_month_sum; /*and all others*/
More information about store procedures with OUT parameters can be found here:
https://dev.mysql.com/doc/refman/8.0/en/create-procedure.html
I'm looking to calculate the expiry date from the set of date, interval number, and period (day, week, month, and year).
Here is my data
Expecting expiry date is 2020-09-24 based on calculation below
((2020-01-22)+8 months)+((2020-01-22)+2 days) = 2020-09-24
I tried with below select query but its not showing expecting output,
SELECT CASE t.cycle_period
WHEN "day" THEN DATE_ADD(t.createdTime, INTERVAL t.cycle_number DAY)
WHEN "week" THEN DATE_ADD(t.createdTime, INTERVAL t.cycle_number WEEK)
WHEN "month" THEN DATE_ADD(t.createdTime, INTERVAL t.cycle_number MONTH)
WHEN "year" THEN DATE_ADD(t.createdTime, INTERVAL t.cycle_number YEAR)
END
AS expiry, t.cycle_period FROM (
SELECT DATE_FORMAT(createdTime,'%Y-%m-%d') AS createdTime,SUM(cycle_number) AS cycle_number,
cycle_period FROM subscriptions
WHERE STATUS='COMPLETED' AND user_id='2'
GROUP BY DATE_FORMAT(createdTime,'%Y-%m-%d'),cycle_period
ORDER BY createdTime DESC) t
Any help please!
SELECT createdTime,
createdTime
+ INTERVAL COALESCE(SUM(CASE WHEN cycle_period = 'YEAR' THEN cycle_number END), 0) YEAR
+ INTERVAL COALESCE(SUM(CASE WHEN cycle_period = 'MONTH' THEN cycle_number END), 0) MONTH
+ INTERVAL COALESCE(SUM(CASE WHEN cycle_period = 'WEEK' THEN cycle_number END), 0) WEEK
+ INTERVAL COALESCE(SUM(CASE WHEN cycle_period = 'DAY' THEN cycle_number END), 0) DAY
AS expiry
FROM subscriptions
GROUP BY createdTime;
fiddle
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
For example, server time is 15:00:00. I run the following query but it gives me wrong result. Here my query
SELECT
CASE
WHEN TIME(NOW()) BETWEEN '08:00:01' AND '10:00:00'
THEN 1
WHEN TIME(NOW()) BETWEEN '14:00:01' AND '08:00:00'
THEN 2
ELSE 0
END AS IdShift
What's wrong with my query ? from that case my expected result is 2. but it give me 0
In a BETWEEN clause you have to specify the lower value first, then the higher value.
So you have to change BETWEEN '14:00:01' AND '08:00:00' to BETWEEN '08:00:00' AND '14:00:01'.
When you want to span from 14:00 to the next day 08:00 you have to include the date.
You could do it like this:
SELECT
CASE
WHEN NOW() BETWEEN CONCAT(CURDATE(), ' 08:00:01') AND CONCAT(CURDATE(), ' 10:00:00')
THEN 1
WHEN NOW() BETWEEN CONCAT(CURDATE(), ' 14:00:01') AND CONCAT(CURDATE() + INTERVAL 1 DAY, ' 08:00:00')
THEN 2
ELSE 0
END AS IdShift
As mentioned in another answer, for between the lower bound is always first. I'm not a fan of between, but you need to split your conditions:
SELECT (CASE WHEN TIME(NOW()) BETWEEN '08:00:01' AND '10:00:00'
THEN 1
WHEN TIME(NOW()) BETWEEN '14:00:01' AND '23:59:59'
THEN 2
WHEN TIME(NOW()) BETWEEN '00:00:00' AND '08:00:00'
THEN 2
ELSE 0
END) AS IdShift
Or, phrase this with or:
SELECT (CASE WHEN TIME(NOW()) > '08:00:00' AND TIME(NOW()) <= '10:00:00'
THEN 1
WHEN TIME(NOW()) > '14:00:00' OR TIME(NOW()) < '08:00:00'
THEN 2
ELSE 0
END) AS IdShift
I would be inclined to shift the logic by a minute or two and use hours:
(case when hour(now()) >= 8 and hour(now()) < 10
then 1
when hour(now()) >= 14 or hour(now()) < 8
then 2
end)
Why am I getting an error with the following code:
SELECT
Hour,
SUM( CASE col WHEN '1' THEN data ELSE 0 END ) AS 'Sun',
SUM( CASE col WHEN '2' THEN data ELSE 0 END ) AS 'Mon',
SUM( CASE col WHEN '3' THEN data ELSE 0 END ) AS 'Tues',
SUM( CASE col WHEN '4' THEN data ELSE 0 END ) AS 'Wed',
SUM( CASE col WHEN '5' THEN data ELSE 0 END ) AS 'Thur',
SUM( CASE col WHEN '6' THEN data ELSE 0 END ) AS 'Fri',
SUM( CASE col WHEN '7' THEN data ELSE 0 END ) AS 'Sat'
FROM (
SELECT
HOUR(arrPurch.PurchaseDate) as HOUR,
DAYOFWEEK(arrPurch.PurchaseDate) as col,
SUM(ROUND(arrPurch.Credits * 1.85 + arrPurch.Price,0)) AS Data
FROM praisecharts_main_new.arrangementPurchases AS arrPurch
INNER JOIN praisecharts_main_new.catalog_dev_arrangements
AS catDEVarr ON arrPurch.ArrangementID = catDEVarr.ArrangementID
INNER JOIN praisecharts_main_new.members
ON arrPurch.MemberID = members.MemberID
GROUP BY HOUR(arrPurch.PurchaseDate), DAYOFWEEK(arrPurch.PurchaseDate)
) AS stats
WHERE
Hour BETWEEN 0 AND 23
-- AND arrPurch.PurchaseDate BETWEEN (CURDATE() - INTERVAL 29 DAY)
-- AND (CURDATE() - INTERVAL 1 DAY)
-- AND arrPurch.PurchaseDate > (CURDATE() - INTERVAL 1 DAY)
GROUP BY Hour WITH ROLLUP
When I don't try to PIVOT the results with the CASE clauses, I don't get an error. Here is an example of a query that works:
SELECT
DAYOFWEEK(arrPurch.PurchaseDate) AS DayWeek,
FORMAT(SUM(arrPurch.Credits*1.85+arrPurch.Price)/4,0) AS `c.Rev`
FROM
praisecharts_main_new.arrangementPurchases AS arrPurch
INNER JOIN praisecharts_main_new.catalog_dev_arrangements AS catDEVarr ON
arrPurch.ArrangementID = catDEVarr.ArrangementID
INNER JOIN praisecharts_main_new.members
ON arrPurch.MemberID = members.MemberID
WHERE arrPurch.PurchaseDate BETWEEN (CURDATE() - INTERVAL 29 DAY)
AND (CURDATE() - INTERVAL 1 DAY)
GROUP BY DayWeek WITH ROLLUP;
LIMIT 14
I was able to find the answer. I moved the WHERE clause up to the embedded SELECT cause above, rather than at the bottom. Here is an example of the code that works.
SELECT
Hour,
SUM( CASE col WHEN '1' THEN data ELSE 0 END ) AS 'Sun',
SUM( CASE col WHEN '2' THEN data ELSE 0 END ) AS 'Mon',
SUM( CASE col WHEN '3' THEN data ELSE 0 END ) AS 'Tues',
SUM( CASE col WHEN '4' THEN data ELSE 0 END ) AS 'Wed',
SUM( CASE col WHEN '5' THEN data ELSE 0 END ) AS 'Thur',
SUM( CASE col WHEN '6' THEN data ELSE 0 END ) AS 'Fri',
SUM( CASE col WHEN '7' THEN data ELSE 0 END ) AS 'Sat'
FROM (
SELECT
HOUR(arrPurch.PurchaseDate) as HOUR,
DAYOFWEEK(arrPurch.PurchaseDate) as col,
SUM(ROUND((arrPurch.Credits * 1.85 + arrPurch.Price)/4,0)) AS data
FROM praisecharts_main_new.arrangementPurchases AS arrPurch
INNER JOIN praisecharts_main_new.catalog_dev_arrangements
AS catDEVarr ON arrPurch.ArrangementID = catDEVarr.ArrangementID
INNER JOIN praisecharts_main_new.members
ON arrPurch.MemberID = members.MemberID
WHERE arrPurch.PurchaseDate BETWEEN (CURDATE() - INTERVAL 29 DAY)
AND (CURDATE() - INTERVAL 1 DAY)
GROUP BY HOUR(arrPurch.PurchaseDate),
DAYOFWEEK(arrPurch.PurchaseDate)
) AS stats
WHERE
Hour BETWEEN 0 AND 23
GROUP BY Hour WITH ROLLUP