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.
Related
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))
)
;
I'm attempting to build a table summarizing sales data by week. In it, I'm trying to have one of the adjacent columns show the sales figures for the same fiscal week during the prior year (which due to my organizations fiscal calendar, had a 53rd week last year). I also have need to compare (Comp Units/Comp Sales) to a period 52 weeks ago which is an entirely different fiscal week (Think Week 9 of 2019 comparing to Week 10 2018).
I've tried using both unions and full outer joins, but given the way the way my data is, they're inefficient (Because this is weekly data, unions ended up being inefficient as I needed to leave the date information out of the initial query, then updating columns in my table to reflect the week the data is for. This is obviously rife with opportunity for error, but also time consuming to do 105 times), or just didn't work (attempting a full outer join was returning the wrong answers for all columns). I've also tried utilizing CTEs as well, and that's not working for me either. I'm currently trying a CASE Statement, but that's also returning a null value. I'm not quite sure where to go next
#STANDARDSQL
SELECT
DTL.SKU_NBR AS SKU_NBR
, SLS.STR_NBR AS STR_NBR
, CONCAT(TRIM(CAST(SKU_HIER.SKU_NBR AS STRING)), ' ', '-', ' ', TRIM(SKU_HIER.SKU_DESC)) AS SKU
, CONCAT(TRIM(CAST(SKU_HIER.EXT_SUB_CLASS_NBR AS STRING)), ' ', '-', ' ', TRIM(SKU_HIER.SUB_CLASS_DESC)) AS SUB_CLASS
, CONCAT(TRIM(CAST(SKU_HIER.EXT_SUB_SC_NBR AS STRING)), ' ', '-', ' ', TRIM(SKU_HIER.SUB_SC_DESC)) AS SUB_SUB_CLASS
, LOCATION.MKT_NM AS MARKET_NAME
, LOCATION.RGN_NM AS REGION_NAME
, LOCATION.DIV_NM AS DIVISION_NAME
, LOCATION.DIV_NBR AS DIVISION_NUMBER
, LOCATION.RGN_NBR AS REGION_NUMBER
, LOCATION.MKT_NBR AS MARKET_NUMBER
, COMP.STR_COMP_IND AS COMP_IND
, COMP.PY_STR_COMP_IND AS PRIOR_COMP_IND
, CALENDAR.FSCL_WK_DESC AS FISCAL_WEEK
, CALENDAR.FSCL_PRD_DESC AS FISCAL_PERIOD
, CALENDAR.FSCL_WK_END_DT AS END_DATE
, CALENDAR.FSCL_WK_BGN_DT AS BEGIN_DATE
, CALENDAR.FSCL_YR AS FISCAL_YEAR_NBR
, CALENDAR.FSCL_WK_NBR AS WEEK_NUMBER
, CALENDAR.FSCL_YR_WK_KEY_VAL AS FISCAL_KEY
, CALENDAR.LY_FYR_WK_KEY_VAL AS LY_FISCAL_KEY
, SUM(COALESCE(DTL.UNT_SLS,0)) AS UNITS
, SUM(COALESCE(DTL.EXT_RETL_AMT,0) + COALESCE(DTL.TOT_GDISC_DTL_AMT,0))
AS SALES
, SUM(CASE
WHEN 1=1 THEN (COALESCE(DTL.EXT_RETL_AMT,0) + COALESCE(DTL.TOT_GDISC_DTL_AMT,0)) * COMP.STR_COMP_IND
ELSE 0 END) AS COMP_SALES
, SUM(CASE
WHEN 1=1 THEN (COALESCE(DTL.UNT_SLS,0)) * COMP.STR_COMP_IND
ELSE 0 END) AS COMP_UNITS
, SUM(CASE
WHEN 1=1 AND SLS.SLS_DT = DATE_SUB(SLS.SLS_DT, INTERVAL 364 DAY)
THEN (COALESCE(DTL.EXT_RETL_AMT,0) +
COALESCE(DTL.TOT_GDISC_DTL_AMT,0)) * COMP.PY_STR_COMP_IND
ELSE NULL END)
AS LY_COMP_SALES
, SUM(CASE
WHEN 1=1 AND SLS.SLS_DT = DATE_SUB(SLS.SLS_DT, INTERVAL 364 DAY)
THEN (COALESCE(DTL.UNT_SLS,0)) * COMP.PY_STR_COMP_IND
ELSE NULL END)
AS LY_COMP_UNITS
, SUM(CASE
WHEN SLS.SLS_DT = DATE_SUB(SLS.SLS_DT, INTERVAL 371 DAY)
THEN (COALESCE(DTL.EXT_RETL_AMT,0) +
COALESCE(DTL.TOT_GDISC_DTL_AMT,0))
ELSE NULL END)
AS LY_SALES
, SUM(CASE
WHEN SLS.SLS_DT = DATE_SUB(SLS.SLS_DT, INTERVAL 371 DAY)
THEN (COALESCE(DTL.UNT_SLS,0))
ELSE NULL END)
AS LY_UNITS
FROM `pr-edw-views.SLS.POS_SLS_TRANS_DTL` AS SLS
INNER JOIN
UNNEST (SLS.DTL) AS DTL
JOIN `pr-edw-views.SHARED.MVNDR_HIER` AS MVNDR
ON DTL.DERIV_MVNDR.MVNDR_NBR = MVNDR.MVNDR_NBR
JOIN `pr-edw-views.SHARED.SKU_HIER_FD` AS SKU_HIER
ON SKU_HIER.SKU_NBR = DTL.SKU_NBR
AND SKU_HIER.SKU_CRT_DT = DTL.SKU_CRT_DT
JOIN `pr-edw-views.SHARED.LOC_HIER_FD` AS LOCATION
ON LOCATION.LOC_NBR = SLS.STR_NBR
JOIN `pr-edw-views.SHARED.CAL_PRD_HIER_FD` AS CALENDAR
ON CALENDAR.CAL_DT = SLS_DT
JOIN `pr-edw-views.SLS.STR_COMP_DAY` AS COMP
ON COMP.CAL_DT = CALENDAR.CAL_DT
AND COMP.STR_NBR = SLS.STR_NBR
WHERE CALENDAR.FSCL_WK_END_DT BETWEEN '2018-01-29' AND '2019-04-07'
AND SLS.SLS_DT BETWEEN '2018-01-29' AND '2019-04-07'
AND POS_TRANS_TYP_CD in ('S', 'R')
AND SKU_HIER.EXT_CLASS_NBR = '025-004'
AND MVNDR.MVNDR_NBR IN (74798, 60002238, 73059, 206820, 76009, 40263, 12879, 76722, 10830, 206823, 87752, 60052261, 70401, 51415, 51414)
AND SKU_HIER.LATEST_SKU_CRT_DT_FLG = TRUE
GROUP BY
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20
I'm currently getting null values in my LY_SALES, LY_UNITS, LY_COMP_SALES and LY_COMP_UNITS columns, though I know there should have been locations with sales of those items from the same period the previous year. What I'm trying to get to is having those prior year values showing up along side the current year values. Any help would be hugely appreciated!
Thanks!
Such a condition can never be fulfilled : SLS.SLS_DT = DATE_SUB(SLS.SLS_DT, INTERVAL 371 DAY). Simply because a SLS_DT is not equal to SLS_DT-371.
You can pre-aggregate the table in a CTE (adding SLS_DT to the group by columns) and then replace the CASE with a join to the pre-aggregated table. Aim at something like this: and it will become something like (notice - no SUM in the case):
CASE WHEN AGGSLS.SLS_DT = DATE_SUB(SLS.SLS_DT, INTERVAL 371 DAY)
THEN (COALESCE(AGGSLS.SUM_EXT_RETL_AMT,0) +
COALESCE(AGGSLS.SUM_TOT_GDISC_DTL_AMT,0))
ELSE NULL END
Two things:
1) WHEN 1=1 can be expressed simply as WHEN TRUE, this way it is easier to move statements around without breaking the AND/OR chaining
2) to get the last year's sales. You can either omit the year from the final query and limit the output with a where clause or create a smaller table that has the sales this year, sales last year per week.
In my humble opinion sales last year for weeknum is the best option, as you can use it elsewhere. But it's pretty similar to what you wr
It would look something like:
SELECT CALENDAR.FSCL_WK_DESC as week_num,
sum(case when year = year(current_date()) then (COALESCE(DTL.UNT_SLS,0)) * COMP.STR_COMP_IND else 0 end) as this_year
sum(case when year = year(current_date())-1 then (COALESCE(DTL.UNT_SLS,0)) * COMP.STR_COMP_IND else 0 end) as last_year
And then you join back to the original table using week_num
Hope you find it useful
Cheers!
I have need to apply certain logic in one of our stored procedures.
We have a parameter #season in the sp.
If #season = 0, then i have to entire years budget value.
if #season = 1, then i have to take tax-season budget values
if #season = 2, then i have to take pre-season budget values.
i derived startdate and enddate of each season
as #SeasonStrt , #SeasonEnd
#SeasonStart is from January 1 to April 30 and #SeasonEnd from May 1 to December 30
I have tried something like below,
SELECT SUM(ISNULL(lab.BudgetAmt,0)),
SUM(ISNULL(lab.ProjectedHours,0))
FROM [dbo].[Budget] bud
WHERE [Year] = #taxyear
AND ((#season = 0) OR (Season= #season))
AND CASE WHEN #season in (1,2)
THEN bud.[week] >= CASE WHEN #season in (1,2)THEN #SeasonStrt ELSE bud.[week] END
AND bud.[week] <= CASE WHEN #season in (1,2)THEN #SeasonStrt ELSE bud.[week] END
Sql server gives syntax error. What will be solution which meets my requirement?
thanks for the help
Try this:
SELECT SUM(ISNULL(lab.BudgetAmt,0)),
SUM(ISNULL(lab.ProjectedHours,0))
FROM [dbo].[Budget] bud
WHERE [Year] = #taxyear
AND
(
((#season = 0) AND (Season = #season))
OR ((#season = 1) AND (bud.[week] >= #SeasonStrt))
OR ((#season = 2) AND (bud.[week] <= #SeasonStrt))
)
So, idea is simple: combine your conditions with OR and specific #season value
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.