I am looking to make a case in a SQL query and assign according to the condition several results.
For example :
Code :
INSERT INTO DESTINATION_TABLE (DT_TRT, NU_QUARTER, NU_YEAR) VALUES
(SELECT
CASE
WHEN #P_DT_TRT# = '1900-00-00'
THEN MAX(TT.DT_CTTT)
ELSE #P_DT_TRT#
END AS DT_TRT,
CASE
WHEN EXTRACT (MONTH FROM DT_TRT) < 4
THEN NU_QUARTER = 4 AND NU_YEAR = EXTRACT (YEAR FROM DT_TRT) - 1
ELSE NU_YEAR = EXTRACT (YEAR FROM DT_TRT)
END
CASE
WHEN EXTRACT (MONTH FROM DT_TRT) < 7
THEN 1
ELSE (CASE WHEN EXTRACT (MONTH FROM DT_TRT) < 10 THEN 2 ELSE 3 END AS NU_QUARTER)
END AS NU_QUARTER
FROM TARGET_TABLE TT);
Algorithm :
-> A date will be given in the programme to enable the calculation (#P_DT_TRT#)
If the parameter is not supplied (value = 1900-00-00)
DT_TRT = the largest constitution date (DT_CTTT) in the target table (TARGET_TABLE TT)
Otherwise DT_TRT = date given in parameter
If DT_TRT month < 4
Quarter = 4
Year = Year of DT_TRT - 1
Otherwise Year = Year of DT_TRT
If DT_TRT month < 7
Quarter = 1
Otherwise
If DT_TRT < 10
Quarter = 2
Otherwise Quarter = 3
Question : Is it possible to integrate several results (DT_TRT, NU_QUARTER, NU_YEAR) in one case ? And if so, what is the syntax ?
I work in Teradata Studio.
Thank you for your answers. :)
This seems to be your logic:
INSERT INTO DESTINATION_TABLE (DT_TRT, NU_QUARTER, NU_YEAR)
VALUES
(
-- If the parameter is not supplied (value = 1900-00-00)
-- DT_TRT = the largest constitution date (DT_CTTT) in the target table (TARGET_TABLE TT)
-- Otherwise DT_TRT = date given in parameter
CASE
WHEN #P_DT_TRT# = '1900-00-00'
THEN (SELECT Max(DT_CTTT) FROM TARGET_TABLE)
ELSE #P_DT_TRT#
END,
-- shift back year/quarter by three months to adjust for company's business year
td_quarter_of_year(Add_Months(DT_TRT, -3)),
Extract(YEAR From Add_Months(DT_TRT, -3))
)
;
Related
I have a date field called BIRTH_DAT and the date of births have been recorded like this:
YYYMMDD, where the second number of the year is missing.
So an example would be a date of birth of 4th March 1978 would appear in this field as: 1780304
The rule in this field is that if it begins with a '1' then the date is in the 1900s, if it begins with a '2' then the date is in the 2000s
So what I want to do is to create another column that shows the correctly written version of the date so I can calculate age from it.
e.g
Column 1 is called BIRTH_DAT and has values:
1801204, 1601228, 1980803 ...
Column 2 is a new column called PROPER_DOB and has values:
19801204, 19601228, 19980803 ...
How do I go about this?
Original answer - post was tagged MySQL:
Using CASE expression and operating on a string with left, substring and concat functions will get you derired result. Based on first character we're replacing:
1 with 19
2 with 20
and for any other case when first letter is not in (1,2) we're printing unsupported date format:
select
birth_dat,
case
when left(birth_dat,1) = '1' then concat('19', substring(birth_dat from 2))
when left(birth_dat,1) = '2' then concat('20', substring(birth_dat from 2))
else 'unsupported date format'
end AS proper_dob
from yourtable
As #Siyual and #JanDoggen suggested, the right format for your column should be DATE which you could achieve by converting the string using specified format with str_to_date function like that:
select
birth_dat,
case
when left(birth_dat,1) = '1' then str_to_date(concat('19', substring(birth_dat from 2)), '%Y%m%d')
when left(birth_dat,1) = '2' then str_to_date(concat('20', substring(birth_dat from 2)), '%Y%m%d')
else 'unsupported date format'
end AS proper_dob
from yourtable
Live example for both queries: SQL fiddle
It turns out that OP is using SQL Server, so here's the edited answer:
Use CAST / CONVERT to achieve the same thing since there is not str_to_date function in SQL Server.
Use STUFF for inserting string in the another string value
SELECT *,
YEAR(GETDATE())-YEAR(PROPER_DATE) AS Age,
CASE WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) < 19 THEN '0-19y' ELSE '20y+' END AS AGE_GROUP
FROM(
SELECT BIRTH_DAT,
CASE WHEN CHARINDEX('1',BIRTH_DAT) = 1 THEN STUFF(CAST(BIRTH_DAT AS VARCHAR(30)),2,0,'9')
WHEN CHARINDEX('2',BIRTH_DAT) = 1 THEN STUFF(CAST(BIRTH_DAT AS VARCHAR(30)),2,0,'0')
END AS PROPER_DATE
FROM my_table
)M
SELECT *,YEAR(GETDATE())-YEAR(PROPER_DATE) AS Age,
CASE
WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) < 5 THEN '0-5Y'
WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) BETWEEN 5 AND 9 THEN '5-9Y'
WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) BETWEEN 10 AND 14 THEN '10-14Y'
WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) BETWEEN 15 AND 19 THEN '15-19Y'
WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) >= 20 THEN '20+Y'
ELSE 'NK'
END AS AGE_GROUP,
COUNT(*)
FROM(
SELECT BIRTH_DAT
,SEX
,CASE
WHEN CHARINDEX('1',BIRTH_DAT) = 1 THEN STUFF(CAST(BIRTH_DAT AS VARCHAR(10)),2,0,'9')
WHEN CHARINDEX('2',BIRTH_DAT) = 1 THEN STUFF(CAST(BIRTH_DAT AS VARCHAR(10)),2,0,'0')
END AS PROPER_DATE
FROM mytable
)M
GROUP BY (CASE
WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) < 5 THEN '0-5Y'
WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) BETWEEN 5 AND 9 THEN '5-9Y'
WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) BETWEEN 10 AND 14 THEN '10-14Y'
WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) BETWEEN 15 AND 19 THEN '15-19Y'
WHEN YEAR(GETDATE())-YEAR(PROPER_DATE) >= 20 THEN '20+Y'
ELSE 'NK'
END
I am trying to determine all sales within the current financial year and wanted to incorporate an If statement as a calculated field to do so. Please see my code below.
SELECT RtnUserId, COUNT(*) AS Returns_, RtnDt, COUNT(RtnDt) AS DtRet,
IF
BEGIN
YEAR(RtnDt) = YEAR(GETDATE()) AND MONTH(RtnDt) >= 4
RETURN 'INDATE'
END as Financial_Period
FROM dbo.vw_AN_Admin_VendorReturns
WHERE (RtnUserId = 'BEND1') OR
(RtnUserId = 'DEENA') OR
(RtnUserId = 'RICHARDK2')
GROUP BY RtnUserId, RtnDt,
IF
BEGIN
YEAR(RtnDt) = YEAR(GETDATE()) AND MONTH(RtnDt) >= 4
RETURN'INDATE'
END
I have created a calendar table that contains all the calendar dates of a year, incl. the corresponding quarter / week / month / day etc. information.
The following Select gives me a specific date, here the 17th of March.
How can I extend the below to check if this falls on a Saturday or Sunday (weekDayCal = 7 or 1) and, if true, return the date for the following Monday, otherwise return the 17th ?
SELECT *
FROM Calendar
WHERE (yearCal = 2014) AND (monthCal = 3) AND (dayCal = 17)
Many thanks in advance for any help with this, Mike.
Assuming you have a day_of_calendar style id field, where every date is sequentially in order, then this works...
SELECT *
FROM Calendar
WHERE id = (SELECT id + CASE weekDayCal WHEN 7 THEN 2 WHEN 1 THEN 1 ELSE 0 END
FROM Calendar
WHERE (yearCal = 2014) AND (monthCal = 3) AND (dayCal = 17)
)
If not, then you're going to have to return to using dates in one way or another.
For example...
SELECT *
FROM Calendar
WHERE realDate = (SELECT realDate + CASE weekDayCal WHEN 7 THEN 2 WHEN 1 THEN 1 ELSE 0 END
FROM Calendar
WHERE (yearCal = 2014) AND (monthCal = 3) AND (dayCal = 17)
)
But then you may as well just use real date calculations.
I think this should work, if you do indeed have a weekDayCal column where 1=Sunday, 2 = Monday and 7 = Saturday:
SELECT *
FROM Calendar
WHERE (yearCal = 2014) AND (monthCal = 3) AND (
(dayCal = 17 and weekDayCal not in (1,7)) OR
(dayCal = 17 + 1 and weekDayCal = 2) OR
(dayCal = 17 + 2 and weekDayCal = 2))
This fetches rows who fall on sunaday or saturday
SELECT *
FROM Calender
WHERE DATEPART(dw, CAST(
CAST(monthCal as VARCHAR(2))+ '-'+
CAST(dayCal as VARCHAR(2))+'-'+
CAST(yearCal as VARCHAR(4))
AS DATETIME
)
) IN(1,7)
I'm creating a report using SQL to pull logged labor hours from our labor database for the previous month. I have it working great, but need to add logic to prevent it from breaking when it runs in January. I've tried adding If/Then statements and CASE logic, but I don't know if I'm just not doing it right, or if our system can't process it. Here's the snippet that pulls the date range:
SELECT
...
FROM
...
WHERE
...
AND
YEAR(ENTERDATE) = YEAR(current date) AND MONTH(ENTERDATE) = (MONTH(current date)-1)
Just use AND as a barrier like this. In January, the second clause will be executed instead of the first one:
SELECT
...
FROM
...
WHERE
...
AND
(
(
(MONTH(current date) > 1) AND
(YEAR(ENTERDATE) = YEAR(current date) AND MONTH(ENTERDATE) = (MONTH(current date)-1))
-- this one gets used from Feb-Dec
)
OR
(
(MONTH(current date) = 1) AND
(YEAR(ENTERDATE) = YEAR(current date) - 1 AND MONTH(ENTERDATE) = 12)
-- alternatively, in Jan only this one gets used
)
)
If your report is always going to be for the previous month, then I think the simplest idea is to declare the year and month of the previous month and then reference those in the Where clause. For example:
Declare LastMo_Month Integer = MONTH(DATEADD(MONTH,-1,getdate()));
Declare LastMo_Year Integer = YEAR(DATEADD(MONTH,-1,getdate()));
Select ...
Where MONTH(EnterDate) = #LastMo_Month
and YEAR(EnterDate) = #LastMo_Year
You could even take it a step further and allow the report to be created for any number of months ago:
Declare Delay Integer = -1;
Declare LastMo_Month Integer = MONTH(DATEADD(MONTH,#Delay,getdate()));
Declare LastMo_Year Integer = YEAR(DATEADD(MONTH,#Delay,getdate()));
Select ...
Where MONTH(EnterDate) = #LastMo_Month
and YEAR(EnterDate) = #LastMo_Year
Hope this helps.
PS - This is my first answer on StackOverflow, so sorry if the formatting isn't right!
if(month(getdate()) = 1)
begin
your jan logic
end
else
begin
your logic
end
The above answer with the Case is ok, but running a CASE on a huge result set would be pretty costly
WHERE
...
AND
DATEPART(yy,ENTERDATE) = DATEPART(yy,DATEADD(m,-1,ENTERDATE))
AND DATEPART(m,ENTERDATE) = DATEPART(m,DATEADD(m,-1,ENTERDATE))
Which Dialect of SQL are you speaking?
As opposed to doing it all with case statements, just use the built it date / time functions to subtract a month from the current date, which should handle crossing year boundaries.
TransACT
WHERE
YEAR(ENTERDATE) = year(dateadd(MONTH,-1, CURRENT_TIMESTAMP))
AND MONTH(ENTERDATE) = month(dateadd(MONTH,-1, CURRENT_TIMESTAMP))
Mysql
WHERE
YEAR(ENTERDATE) = YEAR(date_sub(curdate(),INTERVAL 1 MONTH))
AND MONTH(ENTERDATE) = MONTH(date_sub(curdate(),INTERVAL 1 MONTH) )
Try adding the previous month and year to your SELECT statement:
SELECT
...
,CASE MONTH(current date)
WHEN 1 THEN 12
ELSE MONTH(current date)-1
END AS previous_month
,CASE MONTH(current date)
WHEN 1 THEN YEAR(current date)-1
ELSE YEAR(current date)
END AS previous_year
FROM
...
WHERE
...
AND YEAR(ENTERDATE) = previous_year
AND MONTH(ENTERDATE) = previous_month
This should allow you to set the value before the WHERE comparison. This should be the most performant way to perform this procedure, as it avoids creating two entirely separate clauses or using OR.
I am working on some inherited code, and am having an issue with an SQL Query within it. The query is as follows.
Select distinct
g.scriptid,
g.procedurename,
h.parameters,
g.scriptname,
h.usercode,
h.facility,
h.recid,
cast((cast(recid as varchar) + '.' + Right('0000' + cast(scriptgennum as varchar), 4)) as decimal(10,4)) as 'scriptrecid',
scriptgennum+1 as 'scriptgennum',
h.generated,
h.runinterval,
case
when runinterval = 'M' then dateadd(month,1,convert(varchar(10),h.nextrundate,120))
when runinterval = 'Q' then dateadd(month,3,convert(varchar(10),h.nextrundate,120))
when runinterval = 'W' then dateadd(week,1,convert(varchar(10),h.nextrundate,120))
when runinterval = '0' then NULL end as 'nextrundate',
convert(varchar(10),getdate(),120) as currentrundate,
scripttype
from PATIENTLETTERS_SCRIPTHIST h join PATIENTLETTERS_SCRIPTS g on
g.scriptid = h.scriptid where
h.status = 'Y'
and (([runinterval] = 'M'
and (convert(varchar(10),nextrundate,120) = convert(varchar(10),getdate(),120)
and datepart(day,getdate()) = 5
and (datediff(month,convert(varchar(10),h.lastrundate,120),convert(varchar(10),getdate(),120)) = 1)
or lastrundate is null))
or ([runinterval] = 'Q'
and (convert(varchar(10),nextrundate,120) = convert(varchar(10),getdate(),120)
and datepart(weekday,getdate()) = 0
and (datediff(month,convert(varchar(10),h.lastrundate,120),convert(varchar(10),getdate(),120)) = 3)
or lastrundate is null))
or ([runinterval] = 'W'
and (convert(varchar(10),nextrundate,120) = convert(varchar(10),getdate(),120)
and datepart(day,getdate()) = 5
and (datediff(week,convert(varchar(10),h.lastrundate,120),convert(varchar(10),getdate(),120)) = 1)
or lastrundate is null))
or ([runinterval] = 'O'
and (convert(varchar(10),nextrundate,120) = convert(varchar(10),getdate(),120)
and (datepart(weekday,getdate()) = 0))
or lastrundate is null))
I know that it is trying to select the specific columns listed from PATIENTLETTERS_SCRIPTHIST and PATIENTLETTERS_SCRIPTS. The part of the query that has me confused are the lines like these:
and (([runinterval] = 'M'
and (convert(varchar(10),nextrundate,120) = convert(varchar(10),getdate(),120)
and datepart(day,getdate()) = 5
and (datediff(month,convert(varchar(10),h.lastrundate,120),convert(varchar(10),getdate(),120)) = 1)
If someone can explain what those lines are actually doing I would greatly appreciate any help. I can see that it wants to make sure that the run interval is 'M', and it looks like its trying to match up the current date to the day in stored in the database in the 4th line, but the 2nd and 3rd lines are still a complete mystery.
Looking for items set to run monthly, where the next run date is today, and today is the 5th of the month, and it's been exactly one month since the item was last run.
More info on CONVERT
and DATEPART
This code is looking for items that have a runinterval = 'M'
line 1 - [runinterval] = 'M'
and the nextrundate is equal to the current date (getdate()), the dates are being converted to a varchar with the same formatting.
line 2 - and (convert(varchar(10),nextrundate,120) = convert(varchar(10),getdate(),120)
and the current date has a day equal to 5. Meaning that the date would have to be June 5, July 5, etc
line 3 - and datepart(day,getdate()) = 5
and the difference between the month of the lastrundate and the current date (getdate()) is equal to 1
line 4 - (datediff(month,convert(varchar(10),h.lastrundate,120),convert(varchar(10),getdate(),120)) = 1)
The second line converts nextrundate and the current date to 'YYYY-MM-DD' format using style 120 (More details here) then checks that they're the same, so only rows where nextrundate is today.
The third line just checks that today is the 5th day of the month. For instance:
SELECT DATEPART(DAY, '2012-07-05') returns 5.