MySQL query error...it does not display the exact data values - mysql

I want to ask if what is wrong (and probably ask for suggestions on how to better do it) with my MySQL query? I'm trying to generate a daily report within a range of 5days... the problem is it does not display the exact datas, It fills up days that does not have data in it.
This is the case of the MySQL query example below:
In my database, monday, wed and thursday are with datas.. but if I will run the reports using this query, tuesday will have an existing data which it does not actually has in my database. Although the IT, NonIt, and Total table count is correct. I have errors in counting the datas in my days only. please help me... I don't know where the errors already.
To better explain what I mean, here is the screenshot of the output result of my query:
http://www.fileden.com/files/2011/7/27/3174077//daily.JPG
SELECT a.specialist_partner_ID, ss.first_name as SS, ssa.first_name as SSA
,count(CASE WHEN a.receivedDate BETWEEN '2011-09-5' AND '2011-09-9'
THEN a.job_order_number ELSE null END) As MON
,count(CASE WHEN a.receivedDate BETWEEN date_add('2011-09-5', INTERVAL 1 DAY)
AND DATE_ADD('2011-09-9', INTERVAL 1 DAY) THEN a.job_order_number ELSE null END) As TUE
,count(CASE WHEN a.receivedDate BETWEEN date_add('2011-09-5', INTERVAL 2 DAY)
AND DATE_ADD('2011-09-9', INTERVAL 2 DAY) THEN a.job_order_number ELSE null END) As WED
,count(CASE WHEN a.receivedDate BETWEEN date_add('2011-09-5', INTERVAL 3 DAY)
AND DATE_ADD('2011-09-9', INTERVAL 3 DAY) THEN a.job_order_number ELSE null END) As THU
,count(CASE WHEN a.receivedDate BETWEEN date_add('2011-09-5', INTERVAL 4 DAY)
AND DATE_ADD('2011-09-9', INTERVAL 4 DAY) THEN a.job_order_number ELSE null END) As FRI
,count(case WHEN (a.receivedDate between '2011-09-5 00:00:00' and '2011-09-9 23:59:59'
and jo.job_order_type LIKE 'IT') then a.job_order_number else null end) as IT
,count(case WHEN (a.receivedDate between '2011-09-5 00:00:00' and '2011-09-9 23:59:59'
and jo.job_order_type LIKE 'Non-IT') then a.job_order_number else null end) as NonIT
,count(a.job_order_number) As Total FROM jo_partner a
left join specialist_partner sp on a.specialist_Partner_ID = sp.specialistPartnerID
left join staffing_specialist_asst ssa on sp.SSA_ID = ssa.SSA_ID
left join staffing_specialist ss on sp.SS_ID = ss.SS_ID
left join job_order jo on a.job_order_number = jo.job_order_number
left join candidate_jo cjo on a.JO_partner_ID= cjo.jo_partner_ID
left join candidate can on cjo.candidate_jo_ID= can.candidate_ID
WHERE a.receivedDate BETWEEN '2011-09-5 00:00:00' AND '2011-09-9 23:59:59'
GROUP BY a.specialist_partner_ID

I think you have wrong dates. For every day column you are selecting data from 5 days, this has no sense.
So instead of:
count(CASE WHEN a.receivedDate BETWEEN date_add('2011-09-5', INTERVAL 1 DAY)
AND DATE_ADD('2011-09-9', INTERVAL 1 DAY) THEN a.job_order_number ELSE null END) As TUE
You should have:
count(CASE WHEN a.receivedDate BETWEEN date_add('2011-09-5', INTERVAL 1 DAY)
and DATE_ADD('2011-09-5', INTERVAL 2 DAY) THEN a.job_order_number ELSE null END) As TUE
Or even better:
count(CASE WHEN a.receivedDate >= date_add('2011-09-5', INTERVAL 1 DAY)
and a.receivedDate < DATE_ADD('2011-09-5', INTERVAL 2 DAY) THEN a.job_order_number ELSE null END) As TUE
The same for the rest of the days.

Related

How to count number of nights booked per month with check-in and check-out dates having different months in SQL?

I have a dataset like the below dataset. I want to find the number of nights each id was occupied per month. For some rows, the check-in and checkout dates are in different months. I want to know how to write a query to have the occupancy per month. For example, for id=1, check-in: 2020-01-26 and checkout date: 2020-03-02. How can I have a table that shows January occupancy: 6, Feb occupancy: 29, and March occupancy: 1
id
check-in
checkout
1
2020-01-26
2020-03-02
2
2020-04-01
2020-04-20
3
2020-06-29
2020-07-03
The outcome should be like this:
id
Month
Occupancy
1
Jan
06
1
Feb
29
1
Mar
01
2
Apr
19
3
Jun
02
3
Jul
02
first, you need a numbers table or tally table , after you can easily to it using this query :
select c.id,
case when m.id <> 0
then adddate(last_day(adddate(checkin_date, interval m.id -1 month)),interval 1 day)
else checkin_date
end as Checkin_date,
case when last_day(adddate(checkin_date, interval m.id month)) > checkout_date
then checkout_date
else last_day(adddate(checkin_date, interval m.id month))
end checout_date,
datediff(case when last_day(adddate(checkin_date, interval m.id month)) > checkout_date
then checkout_date
else last_day(adddate(checkin_date, interval m.id month)) end,
case when m.id <> 0
then last_day(adddate(checkin_date, interval m.id -1 month))
else adddate(checkin_date, interval -1 day) end
) daysdiff
from checkins c
join numbers m on m.id <= period_diff(date_format(checkout_date, "%Y%m"),date_format(checkin_date, "%Y%m"))
order by c.id, checkin_date
this is works for any gap (for more than 1 year)
you can usedate_format to show month :
select
date_format(case when m.id <> 0
then adddate(last_day(adddate(checkin_date, interval m.id -1 month)),interval 1 day)
else checkin_date
end, '%Y %M') as month_year
,sum(datediff(case when last_day(adddate(checkin_date, interval m.id month)) > checkout_date
then checkout_date
else last_day(adddate(checkin_date, interval m.id month)) end,
case when m.id <> 0
then last_day(adddate(checkin_date, interval m.id -1 month))
else adddate(checkin_date, interval -1 day) end
)) Occupancy
from checkins c
join numbers m on m.id <= period_diff(date_format(checkout_date, "%Y%m"),date_format(checkin_date, "%Y%m"))
group by date_format(case when m.id <> 0
then adddate(last_day(adddate(checkin_date, interval m.id -1 month)),interval 1 day)
else checkin_date
end, '%Y %M')
order by month_year
month_year | Occupancy
:------------ | --------:
2020 April | 20
2020 February | 29
2020 January | 6
2020 July | 3
2020 June | 2
2020 March | 2
db<>fiddle here
If I understand correctly, you want month-wise aggregated result of occupied inventory.
You can try below simple aggregate query as based on 'Group by' clause then add more criteria logic based on your need if required
select monthname(check_in) as 'Month', sum(dayofyear(check_out) - dayofyear(check_in)) as 'Occupied_days'
from inventory
where year(check_in)=year(check_out)
group by 1;
Note: Above query will work only for dataset where check_in & check_out happened within same year.
Check sample query output here in Fiddle

How to get count and sum with multiple parameter in case when

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

SQL turnover of the day before last year

I'm blocking on an SQL query. I am looking to recover the turnover of last year but the day before. For example: we are the 13/08/19 and I wish the turnover of yesterday of last year so 12/08/18.
How can I do that? Here is my request:
SELECT SUM(total_paid/1.2)
FROM '._DB_PREFIX_.'orders
WHERE o.date_add BETWEEN DATE_FORMAT(
CASE
WHEN YEAR( DATE_SUB( now(), INTERVAL 364 DAY ) ) = YEAR(now() )
THEN DATE_SUB(concat(YEAR(now()),'-',MONTH(now()),'-01'), INTERVAL 371 DAY)
ELSE DATE_SUB(concat(YEAR(now()),'-',MONTH(now()),'-01'), INTERVAL 364 DAY) END, '%Y/%m/%d') AND
CASE
WHEN YEAR( DATE_SUB( now(), INTERVAL 364 DAY ) ) = YEAR(now() )
THEN DATE_SUB(now(), INTERVAL 371 DAY)
ELSE DATE_SUB(now(), INTERVAL 364 DAY) END
AND valid=1
table
Thanks for help.
It seems you should be able to simplify your query to something like this:
SELECT SUM(total_paid/1.2)
FROM '._DB_PREFIX_.'orders
WHERE DATE(o.date_add) = CURDATE() - INTERVAL 1 YEAR - INTERVAL 1 DAY
Note that dependent on how you want to treat February 29, you may want to change the expression to
CURDATE() - INTERVAL 1 DAY - INTERVAL 1 YEAR
In the first form, 2020-02-29 will map to 2019-02-27, in the second it will map to 2019-02-28.
{
select sum(your_total_column/1.2) from your_tab
where now() =(CASE WHEN mod(year(your_date_column),4) = 0
THEN DATE_ADD(your_date_column,INTERVAL 367 DAY)
ELSE DATE_ADD(your_date_column,INTERVAL 366 DAY));}
The idea is find if your_date_column is leap year if it is leap year then add 367 else add 366 and compare with current date.

Get data from different timeframe

I have this query
SELECT concat(order_delivery_data.order_delivery_data_name,' sent'),
sum(case `order`.order_status when 'sent' then 1 else 0 end) '0-7 days'
FROM order_delivery_data
INNER JOIN `order` ON order_delivery_data.order_id = `order`.order_id
where order_delivery_data.order_delivery_data_name in ('Казахстан КАЗПОЧТА')
and order_statusUpdatedAt >= DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)
UNION
SELECT concat(order_delivery_data.order_delivery_data_name,' parcelonaplace'),
sum(case `order`.order_status when 'parcel-on-a-place' then 1 else 0 end) parcelonaplace
FROM order_delivery_data
INNER JOIN `order` ON order_delivery_data.order_id = `order`.order_id
where order_delivery_data.order_delivery_data_name in ('Казахстан КАЗПОЧТА')
and order_statusUpdatedAt >= DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY)
Which is show 2 columns.
How get one more columns in same query like this?
Use conditional aggregation in your case statements and alter your where clause.
Depending on desired results you may need to alter the 2nd sum to use a between date range instead of just > interval of 14 days.
SELECT concat(order_delivery_data.order_delivery_data_name,' sent'),
sum(case When `order`.order_status = 'sent'
AND order_statusUpdatedAt >= DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY) then 1 else 0 end) '0-7 days',
sum(case When `order`.order_status = 'sent'
AND order_statusUpdatedAt >= DATE_SUB(CURRENT_DATE, INTERVAL 14 DAY) then 1 else 0 end) '8-14 days'
FROM order_delivery_data
INNER JOIN `order` ON order_delivery_data.order_id = `order`.order_id
WHERE order_delivery_data.order_delivery_data_name in ('Казахстан КАЗПОЧТА')
AND order_statusUpdatedAt >= DATE_SUB(CURRENT_DATE, INTERVAL 14 DAY)
UNION
SELECT concat(order_delivery_data.order_delivery_data_name,' parcelonaplace'),
sum(case when `order`.order_status = 'parcel-on-a-place'
AND order_statusUpdatedAt >= DATE_SUB(CURRENT_DATE, INTERVAL 7 DAY) then 1 else 0 end) `parcelonaplace 0-7`,
sum(case when `order`.order_status = 'parcel-on-a-place'
AND order_statusUpdatedAt >= DATE_SUB(CURRENT_DATE, INTERVAL 14 DAY) then 1 else 0 end) `parcelonaplace 8-14
FROM order_delivery_data
INNER JOIN `order` ON order_delivery_data.order_id = `order`.order_id
WHERE order_delivery_data.order_delivery_data_name in ('Казахстан КАЗПОЧТА')
AND order_statusUpdatedAt >= DATE_SUB(CURRENT_DATE, INTERVAL 14 DAY)

I am trying to divide two select queries using sql, not sure if this is possible or not

Below is my query, I think in principle it should work, but am not sure if it is indeed possible or I am thinking too outside the box for this one.
SELECT
(SELECT `orders`.`Status`, COUNT(*) AS COUNT_2 FROM `orders` `sw_orders` WHERE STATUS = 'booking' AND Date(OrderDate) <= CURDATE() AND Date(OrderDate) > DATE_SUB(CURDATE(),INTERVAL 30 DAY)) /
(SELECT `orders`.`Status`, COUNT(*) AS COUNT_2 FROM `orders` `sw_orders` WHERE STATUS = 'quote' AND Date(OrderDate) <= CURDATE() AND Date(OrderDate) > DATE_SUB(CURDATE(),INTERVAL 30 DAY))
AS result
That should return the value of 2 results where bookings is divided by quotes
SELECT count(case when STATUS = 'booking' then 1 end) /
count(case when STATUS = 'quote' then 1 end)
FROM `sw_orders`
WHERE Date(OrderDate) <= CURDATE()
AND Date(OrderDate) > DATE_SUB(CURDATE(),INTERVAL 30 DAY)
select count(status ='booking' or null) / count(status = 'quote') as result from table_name where Date(OrderDate) <= CURDATE() AND Date(OrderDate) > DATE_SUB(CURDATE(),INTERVAL 30 DAY)
Please watch out for syntax error. I have not taken care of.
SELECT
SUM(CASE WHEN STATUS = 'booking' THEN 1 ELSE 0 END) /
SUM(CASE WHEN STATUS = 'quote' THEN 1 ELSE 0 END)
FROM `sw_orders`
WHERE Date(OrderDate) <= CURDATE()
AND Date(OrderDate) > DATE_SUB(CURDATE(),INTERVAL 30 DAY)
I suppose COUNT of STATUS = 'quote' is not 0