sql if statement not working - sql

I can't get this if statement to work.
I'm trying to say 'if(number of dates) is greater than 330, return 'x', otherwise give me the (number of dates)
SELECT if(ROUND(COUNT(ClosedDate) / 10, 0) * 10 > 330 then 'X' else ROUND(COUNT(ClosedDate) / 10, 0) * 10) end AS [Previous Day Sales]
FROM PartsSales
WHERE (MONTH(ClosedDate) = MONTH(GETDATE()))
AND (YEAR(ClosedDate) = YEAR(GETDATE()))
AND (DAY(ClosedDate) = DAY(GETDATE() - 13))

Use a CASE clause:
SELECT CASE WHEN ROUND(COUNT(ClosedDate) / 10, 0) * 10 > 330 then 'X' else ROUND(COUNT(ClosedDate) / 10, 0) * 10 end AS [Previous Day Sales]
FROM PartsSales
WHERE (MONTH(ClosedDate) = MONTH(GETDATE())) AND (YEAR(ClosedDate) = YEAR(GETDATE())) AND (DAY(ClosedDate) = DAY(GETDATE() - 13))

Use CASE:
SELECT
CASE WHEN ROUND(COUNT(ClosedDate) / 10, 0) * 10 > 330
THEN 'X' ELSE ROUND(COUNT(ClosedDate) / 10, 0) * 10) END AS [Previous Day Sales]
FROM PartsSales
WHERE MONTH(ClosedDate) = MONTH(GETDATE())
AND YEAR(ClosedDate) = YEAR(GETDATE())
AND DAY(ClosedDate) = DAY(GETDATE() - 13)

I would recommend:
SELECT (CASE WHEN COUNT(*) >= 335 THEN 'X'
ELSE CAST(ROUND(COUNT(ClosedDate) / 10, 0) * 10) as VARCHAR(255))
END) AS [Previous Day Sales]
FROM PartsSales ps
WHERE CAST(ClosedDate as DATE) = CAST(DATEADD(day, -13, GETDATE()) as DATE);
Notes:
You WHERE clause is too complicated.
Why is the "previous day" using the day from 13 days ago?
Be explicit about the types! You are mixing strings and numbers. The result of the case expression needs to be a string.

Related

Create view with variable declaration defined by a case expression, generating a dynamic date table based on getdate() reference

I have static date table and a working query that I use to add references fields for comparison between financial periods, I would like to save as a view however the variable declaration is not permitted.
Query is shown below, the specific issues is with declaring "#this_qtr_month" and calculating "Is QTD". The variable determines [Num of Month in QTR] for today.
declare #this_qtr_month as int = case when month(getdate()) in (1,4,7,10) then 1
when month(getdate()) in (2,5,8,11) then 2
when month(getdate()) in (3,6,9,12) then 3
end
select *
,DATEDIFF(day,[Date],getdate()) as 'Days Aged'
,DATEDIFF(ww,[Date],getdate()) as 'Weeks Aged'
,DATEDIFF(qq,[Date],getdate()) as 'QTRs Aged'
,DATEDIFF(yy,[Date],getdate()) as 'Years Aged'
,case when DATEPART(dd,[Date]) <= DATEPART(dd,getdate()) then 'Y' else 'N' end as 'Is MTD'
,case when #this_qtr_month > [Num of Month in QTR] then 'Y'
when #this_qtr_month = [Num of Month in QTR] and DATEPART(dd,[Date]) <= DATEPART(dd,getdate()) then 'Y'
else 'N'
end as 'Is QTD'
,case when getdate() >= DATEFROMPARTS(year(getdate()), [Month Num], day(date_modified_LeapYear)) then 'Y' else 'N' end as 'Is YTD'
from Date_Table_Static
You could write that without a variable:
SELECT *,
DATEDIFF(DAY, [Date], GETDATE()) AS 'Days Aged',
DATEDIFF(ww, [Date], GETDATE()) AS 'Weeks Aged',
DATEDIFF(qq, [Date], GETDATE()) AS 'QTRs Aged',
DATEDIFF(yy, [Date], GETDATE()) AS 'Years Aged',
CASE
WHEN DATEPART(dd, [Date]) <= DATEPART(dd, GETDATE()) THEN
'Y'
ELSE
'N'
END AS 'Is MTD',
CASE
WHEN (CASE
WHEN MONTH(GETDATE()) IN ( 1, 4, 7, 10 ) THEN
1
WHEN MONTH(GETDATE()) IN ( 2, 5, 8, 11 ) THEN
2
WHEN MONTH(GETDATE()) IN ( 3, 6, 9, 12 ) THEN
3
END
) > [Num of Month in QTR] THEN
'Y'
WHEN (CASE
WHEN MONTH(GETDATE()) IN ( 1, 4, 7, 10 ) THEN
1
WHEN MONTH(GETDATE()) IN ( 2, 5, 8, 11 ) THEN
2
WHEN MONTH(GETDATE()) IN ( 3, 6, 9, 12 ) THEN
3
END
) = [Num of Month in QTR]
AND DATEPART(dd, [Date]) <= DATEPART(dd, GETDATE()) THEN
'Y'
ELSE
'N'
END AS 'Is QTD',
CASE
WHEN GETDATE() >= DATEFROMPARTS(YEAR(GETDATE()), [Month Num], DAY(date_modified_LeapYear)) THEN
'Y'
ELSE
'N'
END AS 'Is YTD'
FROM Date_Table_Static;
Or, since all you need with this view is a SELECT, you could write that as a Stored Procedure or TVF (Table Valued Function).
EDIT: I didn't read your expression before, it doesn't need to be that complex:
SELECT *,
DATEDIFF(DAY, [Date], GETDATE()) AS 'Days Aged',
DATEDIFF(ww, [Date], GETDATE()) AS 'Weeks Aged',
DATEDIFF(qq, [Date], GETDATE()) AS 'QTRs Aged',
DATEDIFF(yy, [Date], GETDATE()) AS 'Years Aged',
CASE
WHEN DATEPART(dd, [Date]) <= DATEPART(dd, GETDATE()) THEN
'Y'
ELSE
'N'
END AS 'Is MTD',
CASE
WHEN (Month(Getdate())-1)%3+1 > [Num of Month in QTR] THEN
'Y'
WHEN (Month(Getdate())-1)%3+1 = [Num of Month in QTR]
AND DATEPART(dd, [Date]) <= DATEPART(dd, GETDATE()) THEN
'Y'
ELSE
'N'
END AS 'Is QTD',
CASE
WHEN GETDATE() >= DATEFROMPARTS(YEAR(GETDATE()), [Month Num], DAY(date_modified_LeapYear)) THEN
'Y'
ELSE
'N'
END AS 'Is YTD'
FROM Date_Table_Static;

simplify a SQL case statement in a case expression

How would I simplify this case statement in T-SQL? It provides the desired result, but it's very unwieldy and hard to read. I have to use the inner case statement to convert a Julian date (aka 6 digit number) into a regular date format.
Basically i'm doing a datediff( getdate(), case statement). Getdate() just returns the time now (ie. 2/27/2020) and the case statement converts a julian date (ie. 123456) into a normal date (ie, 1/1/2020).
Here's the expect output if the query was ran today on Feb 27.
Select CASE
WHEN Datediff(day, Getdate(), CASE
WHEN a.wadpl = 0
THEN NULL
ELSE Dateadd(d, Substring(Cast(wadpl AS VARCHAR(6)), 4, 3) - 1, CONVERT(DATETIME, CASE
WHEN LEFT(Cast(wadpl AS VARCHAR(6)), 1) = '1'
THEN '20'
ELSE '21'
END + Substring(Cast(wadpl AS VARCHAR(6)), 2, 2) + '-01-01'))
END) < 0
THEN 'Overdue Now'
WHEN Datediff(day, Getdate(), CASE
WHEN a.wadpl = 0
THEN NULL
ELSE Dateadd(d, Substring(Cast(wadpl AS VARCHAR(6)), 4, 3) - 1, CONVERT(DATETIME, CASE
WHEN LEFT(Cast(wadpl AS VARCHAR(6)), 1) = '1'
THEN '20'
ELSE '21'
END + Substring(Cast(wadpl AS VARCHAR(6)), 2, 2) + '-01-01'))
END) <= 30
THEN 'Coming due in 01-30 days'
ELSE 'Not Overdue'
END [Overdue Status]
FROM Table_X
Here is a easy one to understand, assuming a.wadpl is an integer:
SELECT CASE
WHEN DATEDIFF(DAY, GETDATE(), DATEADD(DAY, a.wadpl % 1000, DATEADD(YEAR,a.wadpl / 1000,'1899-12-31'))) <0 THEN 'Overdue now'
WHEN DATEDIFF(DAY, GETDATE(), DATEADD(DAY, a.wadpl % 1000, DATEADD(YEAR,a.wadpl / 1000,'1899-12-31'))) <= 30 THEN 'Coming due in 01-30 days'
ELSE 'Not Overdue'
END [Overdue Status]
FROM Table_X
or you can simplify by using a subquery (or you can use a WITH):
SELECT CASE
WHEN Age <0 THEN 'Overdue now'
WHEN Age <= 30 THEN 'Coming due in 01-30 days'
ELSE 'Not Overdue'
END [Overdue Status]
FROM (
SELECT DATEDIFF(DAY,GETDATE(),
DATEADD(DAY,wadpl%1000,DATEADD(YEAR,wadpl/1000,'1899-12-31'))) Age, *
FROM Table_X) a
This will of course cause you to do this arithmetic for each row, and you can't easily use any indexes. If you were asking about aggregates, then I would suggest doing the opposite, and pre-calculating the dates and use those in your query instead. You might also want to consider putting a persisted computed column on table_x:
ALTER TABLE TABLE_X
ADD wadpl_dt AS
(DATEADD(DAY,wadpl%1000,DATEADD(YEAR,wadpl/1000,'1899-12-31'))) PERSISTED;
Now you can just refer to table_x.wadpl_dt whenever you want the datetime, and your query would become:
SELECT CASE
WHEN Age <0 THEN 'Overdue now'
WHEN Age <= 30 THEN 'Coming due in 01-30 days'
ELSE 'Not Overdue'
END [Overdue Status]
FROM (
SELECT DATEDIFF(DAY,GETDATE(), wadpl_dt) Age, *
FROM Table_X) a
Here is the easy way to convert a date to what you refer to as the julian date:
SELECT (DATEPART(YEAR,GETDATE())-1900) * 1000 + DATEPART(DAYOFYEAR, GETDATE())
And this is how you can use it:
DECLARE #overdue int;
DECLARE #next30 int;
SET #overdue = (SELECT (DATEPART(YEAR,GETDATE())-1900) * 1000 + DATEPART(DAYOFYEAR, GETDATE()));
SET #next30 = (SELECT (DATEPART(YEAR,GETDATE()+30)-1900) * 1000 + DATEPART(DAYOFYEAR, GETDATE()+30));
SELECT CASE
WHEN wadpl < #overdue THEN 'Overdue now'
WHEN wadpl <= #next30 THEN 'Coming due in 01-30 days'
ELSE 'Not Overdue'
END [Overdue Status]
FROM Table_X

CASE WHEN using AND statement in SQL

I have a query like this :
SELECT
CASE
WHEN (CONVERT(INT, (datepart(DD, A.CIDATE))) AND Year(getDate()) = 2016 ) <= 15
THEN CONVERT(INT,(datepart(MM,A.CIDATE)))
WHEN CONVERT(INT, (datepart(DD, A.CIDATE))) > 15
THEN CONVERT(INT, (datepart(MM, A.CIDATE))) + 1
ELSE 0
END AS MASA_PAJAK
FROM
V_CLAIM_INTERNAL A
It's working but when I add AND Year(getDate()) = 2016 it throws an error:
Msg 4145, Level 15, State 1, Line 1
An expression of non-boolean type specified in a context where a condition is expected, near 'AND'.
I try to make convert also but still having the same error.
SELECT
CASE
WHEN ((CONVERT(INT, (datepart(DD, A.CIDATE))) AND (convert(int, Year(getDate()) = 2016 ))) <= 15
THEN CONVERT(INT, (datepart(MM, A.CIDATE)))
WHEN CONVERT(INT, (datepart(DD, A.CIDATE))) > 15
THEN CONVERT(INT, (datepart(MM, A.CIDATE))) + 1
ELSE 0
END AS MASA_PAJAK
FROM
V_CLAIM_INTERNAL A
What is my query mistake :?
This is probably what you are intending to do:
SELECT CASE WHEN DATEPART(DD, A.CIDATE) <= 15 AND YEAR(GETDATE()) = 2016
THEN DATEPART(MM, A.CIDATE)
WHEN DATEPART(DD, A.CIDATE) > 15
THEN DATEPART(MM, A.CIDATE) + 1
ELSE 0
END AS MASA_PAJAK
FROM V_CLAIM_INTERNAL A
Note that you don't need to convert/cast the result of calling DATEPART, because it already returns an integer.
SELECT CASE
WHEN (CONVERT(INT,(datepart(DD,A.CIDATE)))<= 15 AND Year(getDate()) = 2016 ) THEN CONVERT(INT,(datepart(MM,A.CIDATE)))
WHEN CONVERT(INT,(datepart(DD,A.CIDATE))) > 15 THEN CONVERT(INT,(datepart(MM,A.CIDATE)))+1
ELSE 0 END AS MASA_PAJAK
FROM V_CLAIM_INTERNAL A
Try this Query:
SELECT CASE WHEN datepart(DD,A.CIDATE)<= 15 AND
Year(getDate()) = 2016
THEN datepart(MM,A.CIDATE)
WHEN datepart(DD,A.CIDATE) > 15
THEN datepart(MM,A.CIDATE) + 1
ELSE 0
END AS MASA_PAJAK
FROM V_CLAIM_INTERNAL A

Joining two queries into one

I have two working queries. Query 1 performs a filter on a large table and returns exactly the data that I need, it looks like this:
/****** QUERY #1 - This query will filter the data ******/
SELECT [WacnId],
[StartDT]
,[EndDT]
,[Group]
,[ID_Agency]
,[TargetUnit_Agency],
case [Group]
when 1 then 'in'
when 0 then 'out'
end as traffic
FROM [GW_20140315].[dbo].[ARC_Calls_ReportView]
WHERE [GroupDisplayID] = 'T802149' OR [ID_Agency] = 'Dispatch' or [TargetUnit_Agency] = 'Dispatch'
order by StartDT
Query #2 acts on the filtered data from Query 1 and produces a 1/2 hourly report. Query 2 looks like this:
/******Query #2- This query will take the filtered data and process it as needed ******/
SELECT dateadd(mi, (datediff(mi, 0, StartDT) / 30) * 30, 0) as HalfHour
, sum(DATEDIFF ( s , [StartDT] , [EndDT] )) as [Total Time (Seconds)],
SUM(CASE WHEN [TargetUnit_Agency] = 'Dispatch' then 1 ELSE 0 END ) AS InCount,
SUM(CASE WHEN [ID_Agency] = 'Dispatch' then 1 ELSE 0 END ) AS OutCount
FROM [Radio].[dbo].[Filter_Data]--This is how I did it before, but now I want to combine the two queries
GROUP BY dateadd(mi, (datediff(mi, 0, StartDT) / 30) * 30, 0)
ORDER BY 1
How may I combine these two queries into one?
You may use a CTE to describe your filtered data (first query) and then query using the CTE as your main table (second query):
;WITH FilteredCTE AS
(
SELECT [WacnId],
[StartDT]
,[EndDT]
,[Group]
,[ID_Agency]
,[TargetUnit_Agency],
case [Group]
when 1 then 'in'
when 0 then 'out'
end as traffic
FROM [GW_20140315].[dbo].[ARC_Calls_ReportView]
WHERE [GroupDisplayID] = 'T802149'
OR [ID_Agency] = 'Dispatch'
or [TargetUnit_Agency] = 'Dispatch'
)
SELECT dateadd(mi, (datediff(mi, 0, StartDT) / 30) * 30, 0) as HalfHour,
sum(DATEDIFF ( s , [StartDT] , [EndDT] )) as [Total Time (Seconds)],
SUM(CASE WHEN [TargetUnit_Agency] = 'Dispatch' then 1 ELSE 0 END ) AS InCount,
SUM(CASE WHEN [ID_Agency] = 'Dispatch' then 1 ELSE 0 END ) AS OutCount
FROM FilteredCTE
GROUP BY dateadd(mi, (datediff(mi, 0, StartDT) / 30) * 30, 0)
ORDER BY StartDT
Just select Query1 FROM Query2:
SELECT Dateadd(mi, ( Datediff(mi, 0, startdt) / 30 ) * 30, 0) AS HalfHour,
Sum(Datediff (s, [startdt], [enddt])) AS
[Total Time (Seconds)],
Sum(CASE
WHEN [targetunit_agency] = 'Dispatch' THEN 1
ELSE 0
end) AS InCount,
Sum(CASE
WHEN [id_agency] = 'Dispatch' THEN 1
ELSE 0
end) AS OutCount
FROM (SELECT [wacnid],
[startdt],
[enddt],
[group],
[id_agency],
[targetunit_agency],
CASE [group]
WHEN 1 THEN 'in'
WHEN 0 THEN 'out'
end AS traffic
FROM [GW_20140315].[dbo].[arc_calls_reportview]
WHERE [groupdisplayid] = 'T802149'
OR [id_agency] = 'Dispatch'
OR [targetunit_agency] = 'Dispatch'
ORDER BY startdt)
GROUP BY Dateadd(mi, ( Datediff(mi, 0, startdt) / 30 ) * 30, 0)
ORDER BY 1

Select rolling date range from year/month instead of date field

I need to select the last 12 months of rolling demand from a table that contains the following fields:
Item,
Year,
Month,
Demand Qty
I have tried the following:
Select Item, [Year], [Month],[Demand QTY]
FROM [table1]
Where
(
[Year] >= Year(getdate())-'1'
and [Month] >= Month(getdate())
)
and
(
[Year] < year(getdate())+'1'
and [Month] <= month(getdate())
)
but I am only getting the records for last year and this year of the current month.
Item Year Month Demand Qty
CD051 2011 3 8800
CD051 2012 3 0
I'm still a rookie so I could be making obvious mistakes. Could someone please help me?
Try:
Select Item, [Year], [Month],[Demand QTY]
FROM [table1]
Where ( [Year] = Year(getdate())-'1' and [Month] >= Month(getdate()) ) or
( [Year] = year(getdate()) and [Month] <= month(getdate()) )
The best way to do this:
Select * from TableName where (([Year] * 100) + [Month]) >= ((Year(DateAdd(mm, -12, GetDate())) * 100) + (Month(DateAdd(mm, -12, GetDate()))))
This will only give you between 12 months ago and today
Select * from TableName where (([Year] * 100) + [Month]) between ((Year(DateAdd(mm, -12, GetDate())) * 100) + (Month(DateAdd(mm, -12, GetDate())))) and (Year(GetDate()) * 100 + Month(GetDate()))
For an average, you should be able to add
Select [Year], [Month], Avg([Demand QTY]) AvgDemand from TableName where (([Year] * 100) + [Month]) between ((Year(DateAdd(mm, -12, GetDate())) * 100) + (Month(DateAdd(mm, -12, GetDate())))) and (Year(GetDate()) * 100 + Month(GetDate()))
Group by [Year], [Month]
Just remember that if you have other columns in your query that would make the row unique, you Avg wont give you what you expect