I have the below query that utilizes a case statement. I would like to datediff two dates but exclude weekend days.
I have the below that excutes but now I would like to exclude Sat and Sunday from this... AND DATEDIFF(DD,A.ALERTS_CREATE_DT,S.CreatedDate) <= 2
CASE WHEN
S.Name IN ('Assessment','Survey')
AND A.ALERT_DESC = 'ER'
AND CAST(A.ALERTS_CREATE_DT AS DATE) <= CAST(S.CreatedDate AS DATE)
AND DATEDIFF(DD,A.ALERTS_CREATE_DT,S.CreatedDate) <= 2 /*EXCLUDE Sat and Sunday from the calculation*/
Full Query
SELECT
CASE WHEN
S.Name IN ('Assessment','Survey')
AND A.ALERT_DESC = 'ER'
AND CAST(A.ALERTS_CREATE_DT AS DATE) <= CAST(S.CreatedDate AS DATE)
AND
( DATEDIFF(DD,A.ALERTS_CREATE_DT,S.CreatedDate) <= 2 /*Business Days*/
--DATEDIFF(DD,A.ALERTS_CREATE_DT,S.CreatedDate) + 1
---(DATEDIFF(WK,A.ALERTS_CREATE_DT,S.CreatedDate) * 2)
---(CASE WHEN DATENAME(DW,A.ALERTS_CREATE_DT) = 'SUNDAY' THEN 1 ELSE 0 END)
---(CASE WHEN DATENAME(DW,S.CreatedDate) = 'SATURADAY' THEN 1 ELSE 0 END)
)
THEN 'Y'
WHEN A.ALERT_DESC = 'model' OR S.CreatedDate IS NULL OR S.Name = 'ER'
THEN ''
ELSE 'N'
END 'Count towards Alerts'
FROM A
FULL S ON A.id= S.id
WHERE 1=1
This should give you the required result by excluding the Saturdays and Sundays.
SELECT A.ALERT_DESC,A.ALERTS_CREATE_DT,S.Name,S.CreatedDate,
CASE WHEN
S.Name IN ('Assessment','Survey') AND A.ALERT_DESC = 'ER'
AND CAST(A.ALERTS_CREATE_DT AS DATE) <= CAST(S.CreatedDate AS DATE)
AND
(( DATEDIFF(DD,A.ALERTS_CREATE_DT,S.CreatedDate)+1
- (datediff(wk,A.ALERTS_CREATE_DT,S.CreatedDate)*2)
- case when datepart(dw,A.ALERTS_CREATE_DT)=1 then 1 else 0 end
- case when datepart(dw,S.CreatedDate)=7 then 1 else 0 end
)) <=2 THEN 'Y'
WHEN A.ALERT_DESC = 'model' OR S.CreatedDate IS NULL OR S.Name = 'ER' THEN ''
ELSE 'N' END 'Count towards Alerts'
FROM A,S
Related
I have written the below query individually, but I want in a single query, how to do this, can anyone help..?
SELECT IFNULL(SUM(net_amount),0) as current_date FROM orders WHERE is_cancelled = false and business_date = CURRENT_DATE();
SELECT IFNULL(SUM(net_amount),0) as current_week FROM orders WHERE is_cancelled = false and YEARWEEK(business_date) = YEARWEEK(CURRENT_DATE());
SELECT IFNULL(SUM(net_amount),0) as current_month FROM orders WHERE is_cancelled = false and MONTH(business_date) = MONTH(CURRENT_DATE());
SELECT IFNULL(SUM(net_amount),0) as current_year FROM orders WHERE is_cancelled = false and YEAR(business_date) = YEAR(CURRENT_DATE());
You can use conditional aggregation in order to combine all seperate select statement into unified one such as
SELECT SUM(CASE WHEN business_date = CURRENT_DATE()
THEN
net_amount
ELSE
0
END ) AS current_date,
SUM(CASE WHEN YEARWEEK(business_date) = YEARWEEK(CURRENT_DATE())
THEN
net_amount
ELSE
0
END ) AS current_week,
SUM(CASE WHEN MONTH(business_date) = MONTH(CURRENT_DATE())
THEN
net_amount
ELSE
0
END ) AS current_month,
SUM(CASE WHEN YEAR(business_date) = YEAR(CURRENT_DATE())
THEN
net_amount
ELSE
0
END ) AS current_year
FROM orders
WHERE is_cancelled = false
select
Count(*)
from gl
join TRVMAINDATA msit
on gl.TRANSACTIONID = msit.CHARGETRANSACTIONID
where gl.CREATEDDATETIME >= DATEADD(MONTH,-2,getdate()) AND
datediff(DAY,gl.BUSINESSPROCESSDATE,gl.CREATEDDATETIME)>=4 AND
gl.MARKETCODE In('535','532','056','050','039','036','034','033','030','029','027','023','022','021','018','015','012','011','010','009','007','006','005','002','001' ) and DATEADD(MONTH,DATEDIFF(MONTH,0,gl.CREATEDDATETIME),0) = '2/1/2017 12:00:00 AM'
The above code gives the total for market code mentioned.
But i also want the market code for other code which doesn't belog here. for example
select
Count(*)
from gl
join TRVMAINDATA msit
on gl.TRANSACTIONID = msit.CHARGETRANSACTIONID
where gl.CREATEDDATETIME >= DATEADD(MONTH,-6,getdate()) AND
datediff(DAY,gl.BUSINESSPROCESSDATE,gl.CREATEDDATETIME)>=0
and
DATEADD(MONTH,DATEDIFF(MONTH,0,gl.CREATEDDATETIME),0) = '2/1/2017 12:00:00 AM'
AND
(case
when gl.MARKETCODE In('535','532','056','050','039','036','034','033','030','029','027','023','022','021','018','015','012','011','010','009','007','006','005','002','001') then 'Proprietary'
when gl.MARKETCODE='037' then 'US'
else 'partner'
end )
Is it possible to calculate totals of other market codes in one sql query or do i have to calculate individually?
I think you would like to do count with case when in select statement like this:
SELECT COUNT(CASE
WHEN gl.marketcode IN ( '535', '532', '056', '050',
'039', '036', '034', '033',
'030', '029', '027', '023',
'022', '021', '018', '015',
'012', '011', '010', '009',
'007', '006', '005', '002', '001' ) THEN 1
ELSE NULL
END) AS `Proprietary`,
COUNT(CASE
WHEN gl.marketcode = '037' THEN 1
ELSE NULL
END) AS `US`,
COUNT(CASE
WHEN gl.marketcode NOT IN ( '535', '532', '056', '050',
'039', '036', '034', '033',
'030', '029', '027', '023',
'022', '021', '018', '015',
'012', '011', '010', '009',
'007', '006', '005', '002',
'001', '037' ) THEN 1
ELSE NULL
END) AS `partner`
FROM gl
JOIN trvmaindata msit
ON gl.transactionid = msit.chargetransactionid
WHERE gl.createddatetime >= DATEADD(month, -2, GETDATE())
AND DATEDIFF(day, gl.businessprocessdate, gl.createddatetime) >= 4
AND DATEADD(month, DATEDIFF(month, 0, gl.createddatetime), 0) = '2/1/2017 12:00:00 AM'
SELECT
SQL_CALC_FOUND_ROWS a.* ,
zn.`name` AS zone_name,
c.`name` AS carrier_name,
CASE type
WHEN type=1 THEN 'General day'
ELSE 'Special date' END AS type_changed,
CASE week_day
WHEN week_day = -1 THEN 'notset'
WHEN week_day = 1 THEN 'monday'
WHEN week_day = 2 THEN 'tuesday'
WHEN week_day = 3 THEN 'wednesday'
WHEN week_day = 4 THEN 'thursday'
WHEN week_day = 5 THEN 'friday'
WHEN week_day = 6 THEN 'saturday'
WHEN week_day = 7 THEN 'sunday' END AS week_day_mod ,
IF(date = '0001-01-01 00:00:0', '--', DATE(date)) AS date_mod, IF(is_working_day = 1 ,'working day', 'day off') AS is_working_day_mod
FROM `ps_deliverytime_table` a
LEFT JOIN ps_zone AS zn ON(a.`id_zone` = zn.`id_zone`)
LEFT JOIN ps_carrier AS c ON(a.`id_carrier` = c.`id_carrier`)
WHERE 1 ORDER BY a.`id_time_table` ASC LIMIT 0,50
When week day is equal 1 it works fine but in other case it do not working
When you put column name after CASE, you shouldn't use WHEN column = value, just use WHEN value, because it automatically compares the column to each value in the WHEN clauses.
CASE type
WHEN 1 THEN 'General day'
ELSE 'Special date'
END AS type_changed,
CASE week_day
WHEN -1 THEN 'notset'
WHEN 1 THEN 'monday'
WHEN 2 THEN 'tuesday'
WHEN 3 THEN 'wednesday'
WHEN 4 THEN 'thursday'
WHEN 5 THEN 'friday'
WHEN 6 THEN 'saturday'
WHEN 7 THEN 'sunday'
END AS week_day_mod ,
When you do both, you're testing week_day = (week_day = -1), week_day = (week_day = 1), etc. It works on Monday because 1 = (1 = 1) is equivalent to 1 = 1, which is true; but on Tuesday, it's 2 = (2 = 2), which is equivalent to 2 = 1, which is false.
The following query returns the correct data but I'd like to see if there's a better way of doing this. The query should return the number of cases for each month within a 12 month period where a record exists within the past 2 months. The idea is to get number of accounts that ordered during the month in question and at least one of the previous 2 months. Also, please note that every value in the table for data_date will always be the 1st of the month.
SELECT
sum(
case
WHEN a.data_date = '2013-03-01'
and exists(
select 1 from sales mth1
where mth1.client_id = a.client_id
and
data_date BETWEEN '2013-01-01'
and
'2013-02-01'
)
then case_qty
ELSE 0 END
) AS M1 ,
sum(
case
WHEN a.data_date = '2013-04-01'
and exists(
select 1 from sales mth2
where mth2.client_id = a.client_id
and mth2.data_date BETWEEN '2013-02-01'
and
'2013-03-01'
)
then case_qty
ELSE 0 END
) AS M2 ,
sum( case WHEN a.data_date = '2013-05-01' and exists( select 1 from sales mth3 where mth3.client_id = a.client_id and mth3.data_date BETWEEN '2013-03-01' and '2013-04-01' ) then case_qty ELSE 0 END) AS M3 ,
sum( case WHEN a.data_date = '2013-06-01' and exists( select 1 from sales mth4 where mth4.client_id = a.client_id and mth4.data_date BETWEEN '2013-04-01' and '2013-05-01' ) then case_qty ELSE 0 END) AS M4 ,
sum( case WHEN a.data_date = '2013-07-01' and exists( select 1 from sales mth5 where mth5.client_id = a.client_id and mth5.data_date BETWEEN '2013-05-01' and '2013-06-01' ) then case_qty ELSE 0 END) AS M5 ,
sum( case WHEN a.data_date = '2013-08-01' and exists( select 1 from sales mth6 where mth6.client_id = a.client_id and mth6.data_date BETWEEN '2013-06-01' and '2013-07-01' ) then case_qty ELSE 0 END) AS M6 ,
sum( case WHEN a.data_date = '2013-09-01' and exists( select 1 from sales mth7 where mth7.client_id = a.client_id and mth7.data_date BETWEEN '2013-07-01' and '2013-08-01' ) then case_qty ELSE 0 END) AS M7 ,
sum( case WHEN a.data_date = '2013-10-01' and exists( select 1 from sales mth8 where mth8.client_id = a.client_id and mth8.data_date BETWEEN '2013-08-01' and '2013-09-01' ) then case_qty ELSE 0 END) AS M8 ,
sum( case WHEN a.data_date = '2013-11-01' and exists( select 1 from sales mth9 where mth9.client_id = a.client_id and mth9.data_date BETWEEN '2013-09-01' and '2013-10-01' ) then case_qty ELSE 0 END) AS M9 ,
sum( case WHEN a.data_date = '2013-12-01' and exists( select 1 from sales mth10 where mth10.client_id = a.client_id and mth10.data_date BETWEEN '2013-10-01' and '2013-12-01' ) then case_qty ELSE 0 END) AS M10 ,
sum( case WHEN a.data_date = '2014-01-01' and exists( select 1 from sales mth11 where mth11.client_id = a.client_id and mth11.data_date BETWEEN '2013-11-01' and '2013-12-01' ) then case_qty ELSE 0 END) AS M11
FROM sales as a
INNER JOIN Products AS P ON P.product_id = a.product_id
WHERE a.client_id IN ('123')
AND a.data_date BETWEEN '2013-03-01' AND '2013-12-01' AND a.case_qty > 0;
Here's a screen shot of the explain
Here's a screen shot of the indexes
change
data_date BETWEEN '2013-01-01' and '2013-02-01'
to
data_date in ('2013-01-01', '2013-01-02',.....,...'2013-02-01' )
but i would turn this whole query into sum cases then use a wrapper to pull out the accounts i need.
From your query it seems like you want the years sales for a product in an entire year. Or something to that affect. So from your data you are almost trying to create a pivot. I had a simlar problem and solved it like this
select
p.product_id,
s.client_id,
sum(case when DATE_FORMAT(a.data_date,'%Y%m') in (201301) then ifnull(case_qty,0) else 0 end) period1,
sum(case when DATE_FORMAT(a.data_date,'%Y%m') in (201301, 201302) then ifnull(case_qty,0) else 0 end) period2,
sum(case when DATE_FORMAT(a.data_date,'%Y%m') in (201301, 201302, 201303) then ifnull(case_qty,0) else 0 end) period3,
sum(case when DATE_FORMAT(a.data_date,'%Y%m') in (201302, 201303, 201304) then ifnull(case_qty,0) else 0 end) period4,
sum(case when DATE_FORMAT(a.data_date,'%Y%m') in (201303, 201304, 201305) then ifnull(case_qty,0) else 0 end) period5,
.
.
.
up to period12
from
sales s
where
a.data_date between '2013-03-01' and '2013-12-31' and
s.client_id = some_value
group by
p.product_id,
s.client_id
Note that the performance of the query has increased drastically since you are only doing a single scan of your sales table (depending on what's in your where clause and indexes). To speed it up you would need indexes on say client_id and data_date for example.
Ideally this query would be run for a report or something where the start and end data is fixed and all the user can change is the year of that date. I wasn't sure if you wanted to group by product_id since in your query you aren't, but you can always remove it to get total per client.
I have adjusted the query based on my understanding in your comments. I am not 100% sure if you can use the keyword 'in' in a case statement. You could alternatively have more case statements.
See the SQL query below, it work fine. It calculate the number of Yes, NOT, Other and the number of matching mobile number [Sales field] (D.MobileNo = S.mobile)
SELECT D.Username,
SUM(CASE WHEN D.type = 'Yes' THEN 1 ELSE 0 END) as Yes,
SUM(CASE WHEN D.type = 'Not' THEN 1 ELSE 0 END) as Not,
SUM(CASE WHEN D.type = '' THEN 1 ELSE 0 END) as Other,
SUM(CASE WHEN S.mobile IS NULL THEN 0 ELSE 1 END) as Sales,
COUNT(*) as TOTAL
FROM dairy as D
LEFT JOIN (SELECT DISTINCT mobile FROM sales) as S on D.MobileNo = S.mobile
WHERE source = 'Network'
AND UNIX_TIMESTAMP(CheckDate) >= 1309474800
AND UNIX_TIMESTAMP(CheckDate) <= 1311894000
GROUP BY D.Username
ORDER BY TOTAL DESC
I want to exclude WHERE for the Sales field - it should not be part from CheckDate. Meaning it should check any record in the dairy table without CheckDate for the Sales field.
How can that be done?
If you really want those results in only one query, this might do the trick.
SELECT D.Username,
SUM(CASE WHEN D.type = 'Yes' AND UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1311894000 THEN 1 ELSE 0 END) as Yes,
SUM(CASE WHEN D.type = 'Not' AND UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1311894000 THEN 1 ELSE 0 END) as Not,
SUM(CASE WHEN D.type = '' AND UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1311894000 THEN 1 ELSE 0 END) as Other,
SUM(CASE WHEN S.mobile IS NULL THEN 0 ELSE 1 END) as Sales,
COUNT(*) as TOTAL,
SUM(CASE WHEN UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1311894000 THEN 1 ELSE 0 END) AS TOTALINCHECKDATE
FROM dairy as D
LEFT JOIN (SELECT DISTINCT mobile FROM sales) as S on D.MobileNo = S.mobile
WHERE source = 'Network'
GROUP BY D.Username
ORDER BY TOTAL DESC
Note that "TOTAL" will count all rows (including those who where not within your CheckDate range), TOTALINCHECKDATE return the same value as in your previous query.
Obviously, this can still be optimized.
Assuming username exists also in SALES table
SELECT Username,SUM(Yes) As Yes, SUM(`Not`) As `Not`
, SUM(Other) As Other, SUM(sales) Sales, SUM(total)
FROM (
-- get diary data
SELECT username,mobileNo As mobile,
CASE WHEN D.type = 'Yes' THEN 1 ELSE 0 END as Yes,
CASE WHEN D.type = 'Not' THEN 1 ELSE 0 END as `Not`,
CASE WHEN D.type = '' THEN 1 ELSE 0 END as Other,
0 As sales, 1 as total
FROM dairy as D
WHERE source = 'Network'
AND UNIX_TIMESTAMP(CheckDate) >= 1309474800
AND UNIX_TIMESTAMP(CheckDate) <= 1311894000
UNION ALL
-- get all sales
SELECT DISTINCT username,mobile, 0 as Yes, 0 as `Not`, 0 As Other, 1 As sales, 0 As total
FROM sales
WHERE UNIX_TIMESTAMP(CheckDate) >= 1309474800
AND UNIX_TIMESTAMP(CheckDate) <= 1311894000
) AS a
GROUP BY Username
Also try your original query with date addition
SELECT D.Username,
SUM(CASE WHEN D.type = 'Yes' THEN 1 ELSE 0 END) as Yes,
SUM(CASE WHEN D.type = 'Not' THEN 1 ELSE 0 END) as Not,
SUM(CASE WHEN D.type = '' THEN 1 ELSE 0 END) as Other,
SUM(CASE WHEN S.mobile IS NULL THEN 0 ELSE 1 END) as Sales,
COUNT(*) as TOTAL
FROM dairy as D
LEFT JOIN (SELECT DISTINCT mobile FROM sales WHERE UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1311894000 ) as S on D.MobileNo = S.mobile
WHERE source = 'Network'
AND UNIX_TIMESTAMP(CheckDate) >= 1309474800
AND UNIX_TIMESTAMP(CheckDate) <= 1311894000
GROUP BY D.Username
ORDER BY TOTAL DESC