Snowflake SQL Query - Invalid Argument Function Using DATEADD() - sql

I have the below SQL query I am using in Snowflake where, if the day of the week = Monday, I need to subtract 48 hours from 'HOURS_SINCE_UPDATE':
SELECT DAYNAME(GetDate()) AS DAY,
INC_PUBLIC.INCIDENT_NUMBER,
INC_PUBLIC.COMPANY,
INC_PUBLIC.ASSIGNED_GROUP,
INC_PUBLIC.ASSIGNEE_FULL_NAME,
INC_PUBLIC.ASSIGNEE_ID,
INC_PUBLIC.SUMMARY,
INC_PUBLIC.SUBMIT_DATE_TIME,
INC_PUBLIC.TARGET_DATE_TIME,
INC_PUBLIC.STATUS,
WORK_LOGS.WORK_INFO_TYPE,
WORK_LOGS.SUMMARY,
WORK_LOGS.NOTES,
CASE
WHEN WORK_LOGS.SUBMIT_DATE_TIME IS NULL THEN INC_PUBLIC.SUBMIT_DATE_TIME
ELSE WORK_LOGS.SUBMIT_DATE_TIME
END AS WL_SUBMIT_DATE_TIME,
CASE
WHEN DAY = 'Mon' then DATEADD(HOUR, -48, DATEDIFF(HOURS, WL_SUBMIT_DATE_TIME, GETDATE()))
ELSE DATEDIFF(HOURS, WL_SUBMIT_DATE_TIME, GETDATE())
END AS HOURS_SINCE_UPDATE,
ROW_NUMBER() OVER (PARTITION BY INC_PUBLIC.INCIDENT_NUMBER ORDER BY WORK_LOGS.SUBMIT_DATE_TIME desc) RW,
CASE
WHEN INC_PUBLIC.TARGET_DATE_TIME IS NULL THEN 'Target date is blank'
WHEN TARGET_DATE_TIME < GETDATE() THEN 'Target date expired'
WHEN HOURS_SINCE_UPDATE > 48 THEN 'Overdue for an update'
WHEN INC_PUBLIC.STATUS = 'Assigned' THEN 'Ticket in assigned status'
ELSE 'Good'
END AS REASON_ON_REPORT
FROM SFDW_PROD.SERVICE_MANAGEMENT.INCIDENT_PUBLIC AS INC_PUBLIC
LEFT JOIN
(
SELECT INCIDENT_NUMBER, SUBMIT_DATE_TIME, WORK_INFO_TYPE, SUMMARY, NOTES
FROM SFDW_PROD.SERVICE_MANAGEMENT.INCIDENT_WORK_INFO_PUBLIC
WHERE SUMMARY NOT IN ('Email-Inbound', 'TicketLogger Classification', 'APPMETADATA', 'Auto-Triage Assignment')
AND WORK_INFO_TYPE IN ('Email System', 'Associate Phone Communication','IM Communication','Customer Phone Communication', 'Working Log')
) AS WORK_LOGS
ON INC_PUBLIC.INCIDENT_NUMBER = WORK_LOGS.INCIDENT_NUMBER
WHERE (INC_PUBLIC.ASSIGNED_GROUP LIKE 'DS$_%' ESCAPE '$' AND INC_PUBLIC.STATUS_CODE IN (1,2,3) AND INC_PUBLIC.ASSIGNEE_FULL_NAME != 'NS')
ORDER BY INC_PUBLIC.INCIDENT_NUMBER, WORK_LOGS.SUBMIT_DATE_TIME
limit 100;
CASE
WHEN DAYNAME(GetDate()) = 'Mon' then TIMEADD(HOURS, 48, DATEDIFF(HOUR, WORK_LOGS.SUBMIT_DATE_TIME, GETDATE()))
ELSE DATEDIFF(HOURS, WORK_LOGS.SUBMIT_DATE_TIME, GETDATE())
END AS HOURS_SINCE_UPDATE,
I keep getting the following error:
SQL compilation error: error line 19 at position 30 Invalid argument types for function 'DATE_ADDHOURSTOTIMESTAMP': (NUMBER(2,0), NUMBER(9,0))
What am I doing wrong?

I didn't check the whole query but the error is related to this part:
DATEADD(HOUR, -48, DATEDIFF(HOURS, WL_SUBMIT_DATE_TIME, GETDATE()))
You calculate the time difference (in hours) between WL_SUBMIT_DATE_TIME and the current date. It returns a number, not a date. Then you try to use this number with the DATEADD function, and it expects to have a date instead of a number. This is what you get this error:
If you want to subtract 48 hours, then just subtract it:
DATEDIFF(HOURS, WL_SUBMIT_DATE_TIME, GETDATE()) - 48

Related

group by issue in sql

i'm trying to get in a new column the sessions who are between 08:00 and 18:00. You can see my last CASE in the CTE. For each date there should be a new column "TotalRestrictedSessions" which indicate how many session were on that particular date. If there are none, in this case i have to write 0. I suspect that my problem is when i convert the DATE?
WITH ParkeonCTE
AS
(
SELECT
OccDate = CONVERT(DATE, OC.LocalStartTime),
TotalOccSessions = COUNT(OC.SessionId),
AuthorityId,
TotalOccDuration = ISNULL(SUM(OC.DurationMinutes),0),
TotalNumberOfOverstay = SUM(CAST(OC.IsOverstay AS INT)),
TotalMinOfOverstays = ISNULL(SUM(OC.OverStayDurationMinutes),0),
(CASE
WHEN OC.OspId IS NULL THEN 'OffStreet' ELSE 'OnStreet'
END
) AS ParkingContextType,
(CASE
WHEN CAST(OC.LocalStartTime AS TIME) >= '08:00:00' AND CAST(OC.LocalStartTime AS TIME) <=
'18:00:00'
THEN COUNT(OC.SessionId)
END
) AS TotalRestrictedSessions
FROM Analytics.OccupancySessions AS OC
WHERE OC.AuthorityId IS NOT NULL
GROUP BY CONVERT(DATE,OC.LocalStartTime), OC.AuthorityId,OC.OspId
)
SELECT OC.OccDate,
OC.ParkingContextType,
OC.AuthorityId,
OC.TotalRestrictedSessions,
SUM(OC.TotalOccSessions) AS TotalOccSessions,
AVG(OC.TotalOccDuration) AS AvgOccMinutesDuration, -- wrong
SUM(OC.TotalOccDuration) AS TotalOccDuration,
SUM(OC.TotalNumberOfOverstay) AS TotalNumberOfOverstay,
SUM(OC.TotalMinOfOverstays) AS TotalMinOfOverstays,
CAST(AVG(OC.TotalMinOfOverstays) AS decimal(10,2)) AS AvgMinOfOverstays -- wrong
FROM ParkeonCTE AS OC
GROUP BY OC.OccDate, OC.AuthorityId, OC.ParkingContextType
ORDER BY OC.OccDate DESC
You just need to move your aggregation outside of your CASE expression, called conditional aggregation.
SUM(CASE
WHEN CAST(OC.LocalStartTime AS TIME) >= '08:00:00'
AND CAST(OC.LocalStartTime AS TIME) <= '18:00:00'
THEN 1
ELSE 0
END
) AS TotalRestrictedSessions
Generally, you should include the current query results and your desired results in your question to make it easier to figure out where the issues are.

How to return next year values when you're in the current year, but keep current values when you switch to next year? which becomes current year

I have a view that runs a user selects a certain month. It returns various values based on a month selection. Using MS SQL Server
Problem:
It returns those values based on the month and it works as it should up until a user chooses January. When January is chosen, it brings back both this current year (which has already passed) and this upcoming January (January 2020. Which is what they want). How do I remove the 2019 values when next year is chosen, but also keep them when the year changes to the next year?
Here is the query
SELECT distinct
RRP.Id, RRP.UniqClient, RRP.Client, RRP.Expiring_Policies, RRP.UniqBroker,
CONVERT(varchar, RRP.ExpDate, 101) AS ExpDate, RRP.NewUw, RRP.OtherContact,
RRP.Company, RRP.Broker_Name, RRP.Reviewed, RRP.DateCreated, RRP.DateUpdated,
RRP.EmailCreated, RRP.UniqProducer, RRP.LINES,
CASE WHEN MMS.UniqMarketingSubmission IS NULL THEN 'No' ELSE 'Yes' END AS [MMS Created]
FROM dbo.Reviewed_Renewal_Policy AS RRP LEFT OUTER JOIN
GREEN43_PROD_REPL.dbo.MarketingSubmission AS MMS ON RRP.UniqClient = MMS.UniqEntity AND RRP.ExpDate = MMS.EffectiveDate
where (RRP.Reviewed = 'No') AND (DATENAME(month, RRP.ExpDate) = DATENAME(MONTH, DATEADD(Month, 3, GETDATE())))
order by ExpDate ASC
Typically there is a .NET webforms variable in place of the 3 in DATEADD, but the 3 works in SQL and I kept it for clarity
I have tried messing with comparing current dates and adding a year, but nothing successful so far. Thanks again for your help.
You can add another condition in where cause, try it.
AND YEAR(RRP.ExpDate) = YEAR(GETDATE())
Thanks
If you want the value for three months in the future, I would suggest:
where RRP.Reviewed = 'No' and
RRP.ExpDate >= datefromparts(year(dateadd(month, 3, getdate()),
month(dateadd(month, 3, getdate()),
1) and
RRP.ExpDate < datefromparts(year(dateadd(month, 4, getdate()),
month(dateadd(month, 4, getdate()),
1)
Note: This is constructed so it can use an index on (Reviewed, ExpDate) or (ExpDate).
Just as an example of how much easier it is to read formatted sql. I took the OPs posted answer and formatted it a bit. Removed several extra sets of parenthesis and moved around a little logic so it was a bit simpler.
SELECT distinct RRP.Id
, RRP.UniqClient
, RRP.Client
, RRP.Expiring_Policies
, RRP.UniqBroker
, CONVERT(varchar, RRP.ExpDate, 101) AS ExpDate
, RRP.NewUw
, RRP.OtherContact
, RRP.Company
, RRP.Broker_Name
, RRP.Reviewed
, RRP.DateCreated
, RRP.DateUpdated
, RRP.EmailCreated
, RRP.UniqProducer
, RRP.LINES
, CASE WHEN MMS.UniqMarketingSubmission IS NULL THEN 'No' ELSE 'Yes' END AS [MMS Created]
FROM dbo.Reviewed_Renewal_Policy AS RRP
LEFT OUTER JOIN GREEN43_PROD_REPL.dbo.MarketingSubmission AS MMS ON RRP.UniqClient = MMS.UniqEntity
AND RRP.ExpDate = MMS.EffectiveDate
where RRP.Reviewed = 'No'
AND DATENAME(month, RRP.ExpDate) = DATENAME(MONTH, DATEADD(Month, 4, GETDATE()))
AND
(
Month(getdate()) <= Month(RRP.ExpDate)
)
OR
(
Month(getdate()) > Month(RRP.ExpDate)
AND
Year(RRP.ExpDate) > Year(getdate())
)
order by ExpDate ASC
Appreciate the help I was given. I managed to answer my own question. I found an example of this solution from another question. I modified it to fit my own.
SELECT distinct
RRP.Id, RRP.UniqClient, RRP.Client, RRP.Expiring_Policies, RRP.UniqBroker, CONVERT(varchar, RRP.ExpDate, 101) AS ExpDate,
RRP.NewUw, RRP.OtherContact, RRP.Company, RRP.Broker_Name, RRP.Reviewed, RRP.DateCreated,
RRP.DateUpdated, RRP.EmailCreated, RRP.UniqProducer, RRP.LINES, CASE WHEN MMS.UniqMarketingSubmission IS NULL THEN 'No' ELSE 'Yes' END AS [MMS Created]
FROM dbo.Reviewed_Renewal_Policy AS RRP LEFT OUTER JOIN
GREEN43_PROD_REPL.dbo.MarketingSubmission AS MMS ON RRP.UniqClient = MMS.UniqEntity AND RRP.ExpDate = MMS.EffectiveDate
where ((RRP.Reviewed = 'No') AND (DATENAME(month, RRP.ExpDate) = DATENAME(MONTH, DATEADD(Month, 4, GETDATE())))
AND Month(getdate()) <= Month(RRP.ExpDate))
OR
((RRP.Reviewed = 'No') AND (DATENAME(month, RRP.ExpDate) = DATENAME(MONTH, DATEADD(Month, 4, GETDATE())))
AND Month(getdate()) > Month(RRP.ExpDate) AND Year(RRP.ExpDate) > Year(getdate()))
order by ExpDate ASC
This brings back the current year values and when the next year values when the appropriate selection is made.
OR an Alternative thanks to Gordon Linoff above
SELECT distinct
RRP.Id, RRP.UniqClient, RRP.Client, RRP.Expiring_Policies, RRP.UniqBroker, CONVERT(varchar, RRP.ExpDate, 101) AS ExpDate,
RRP.NewUw, RRP.OtherContact, RRP.Company, RRP.Broker_Name, RRP.Reviewed, RRP.DateCreated,
RRP.DateUpdated, RRP.EmailCreated, RRP.UniqProducer, RRP.LINES, CASE WHEN MMS.UniqMarketingSubmission IS NULL THEN 'No' ELSE 'Yes' END AS [MMS Created]
FROM dbo.Reviewed_Renewal_Policy AS RRP LEFT OUTER JOIN
GREEN43_PROD_REPL.dbo.MarketingSubmission AS MMS ON RRP.UniqClient = MMS.UniqEntity AND RRP.ExpDate = MMS.EffectiveDate
where ((RRP.Reviewed = 'No') AND (DATENAME(month, RRP.ExpDate) = DATENAME(MONTH, DATEADD(Month, 3, GETDATE())))
AND Month(getdate()) <= Month(RRP.ExpDate))
OR
((RRP.Reviewed = 'No') AND (DATENAME(month, RRP.ExpDate) = DATENAME(MONTH, DATEADD(Month, 3, GETDATE()))) AND
datefromparts(1 + year(getdate()), 1, 1) <= RRP.ExpDate and datefromparts(1 + year(getdate()), 2, 1) >= RRP.ExpDate)
order by ExpDate ASC

Need to convert INT to value I can DIFF against

I'm using the below query where the original convert was written for another table with a different date value. The [YMDRCVD] value is (INT, null). I'm using SQL management studio 14 and receiving an Arithmetic overflow error converting expression to data type datetime error message.
SELECT
Year(CH.[YMDRCVD]) as [Receipt date Year],
Month(CH.[YMDRCVD]) as [Receipt Date Month],
COUNT(*) as [Count of Claims],
AVG(convert(numeric(19,2), DATEDIFF(day, CH.[YMDRCVD], CH.[YMDTRANS]))) as [Average Days from Receipt to Initial Finalized] ,
SUM(
CASE WHEN DATEDIFF(day, CH.[YMDRCVD], CH.[YMDTRANS]) > 10 THEN 1
ELSE 0
END) as [Count Processed in > 10 Days]
FROM [SERVICE_X] CH WITH (NOLOCK)
WHERE
CH.[YMDRCVD] >= '1/1/2016'
AND CH.[YMDRCVD] < '6/1/2016'
AND DATEDIFF(day, CH.[YMDRCVD], CH.[YMDTRANS]) < 20
AND DATEDIFF(day, CH.[YMDRCVD], CH.[YMDTRANS]) >= 0
GROUP BY Year(CH.[YMDRCVD]),
Month(CH.[YMDRCVD])
ORDER BY
Year(CH.[YMDRCVD]),
Month(CH.[YMDRCVD])
You are receiving this error because you are trying to call a date function on a value not of data type date / datetime.
You need to convert [YMDRCVD] to date time.
Check out this post: Convert INT to DATETIME (SQL)
Use the following to decode the date:
For YYYYMMDD:
DATEFROMPARTS( FLOOR([YMDRCVD]/10000), FLOOR([YMDRCVD]/100)%100, [YMDRCVD]%100 )

Define a parameter for searching on days DATEADD / datediff - SQL server 2005

So I have now a grouping of values by their currencies and values, which brings out values for the last 30 days, however I would like to search by date, eventually using a parameter from another table.
;WITH cte AS (SELECT ROW_NUMBER() OVER (ORDER BY date_loaded Asc) AS n, value,
date_loaded, cast(round(value * 0.0001 / 100 * 0.5 + (value * 0.0001),4)AS dec(12,4)) as buy_rate,
cast(round(value * 0.0001 / 100 * -0.5 + (value * 0.0001), 4) AS dec(12,4)) as sell_rate
FROM texchange_rate WHERE source_currency_code = #source_currency_code
and target_currency_code = #target_currency_code
and date_loaded between dateadd(day, datediff(day, 0 ,getdate())-30, 0) and getdate())
SELECT t2.value, t2.date_loaded, #source_currency_code as source_currency_code,
#target_currency_code as target_currency_code, t2.buy_rate, t2.sell_rate
FROM cte t2 LEFT JOIN cte t1 ON t2.n = t1.n + 1
WHERE t2.value <> ISNULL(t1.value, -1)
order by date_loaded desc
END
I want to define the amount of days that dateadd searches on from a separate table, is this possible? E.g.
from
dateadd(day, datediff(day, 0 ,getdate())-30, 0) and getdate())
to
dateadd(day, datediff(day, 0 ,getdate())#dayparameter, 0) and getdate())
Just to get this working, I've attempted declaring #dayparameter (similar to here - http://msdn.microsoft.com/en-us/library/ms186819%28v=sql.100%29.aspx, although this is for server 2008) at the start of the stored procedure, and placing it inside dateadd gives the error
Msg 102, Level 15, State 1, Procedure proc_getCurrencyHistory, Line 48
Incorrect syntax near '#dayparameter'.
Hope this makes sense.
You still need to perform an operation. If you want to pass in -30 then you need to add, if you want to pass in 30 then you need to subtract.
If #dayparameter is -30:
dateadd(day, datediff(day, 0 ,getdate()) + #dayparameter, 0) and getdate())
-----------------------------------------^ this operator is important
If #dayparameter is 30:
dateadd(day, datediff(day, 0 ,getdate()) - #dayparameter, 0) and getdate())
-----------------------------------------^ this operator is still important

Calculating number of days between Admission Date and today

I found the following in Stackoverflow and have been working with it to find the number of Patient Days each month. It works very well if I have both the Admit and Discharge dates.
I can't figure out how to edit it to calculate the Patient days when the discharge date has not been completed... the patient is still in the hospital. If feels like I should use Coalesce or ISNULL to find the records where the Discharge Date is NULL, but I'm not a programmer and would appreciate your help.
WITH Mos AS (
SELECT
D.ED_ADMIT_DATE,
D.ED_DISCHARGE_DATE,
Number,
DateAdd(Month, Number, D.ED_ADMIT_DATE - Day(D.ED_ADMIT_DATE) + 1) MoDate
FROM
cases_cstm D
INNER JOIN master.dbo.spt_values V ON V.Number <= DateDiff(Month, D.ED_ADMIT_DATE, D.ED_DISCHARGE_DATE)
WHERE
V.Type = 'P'), Dys AS (
SELECT
MoDate,
DateDiff(
Day,
CASE WHEN Number = 0 THEN ED_ADMIT_DATE ELSE MoDate END,
CASE WHEN Number = DateDiff(Month, ED_ADMIT_DATE, ED_DISCHARGE_DATE) THEN ED_DISCHARGE_DATE ELSE DateAdd(Month, 1, MoDate) -1
END
) + 1 Cnt
FROM Mos)
SELECT Year(MoDate) Yr,
Coalesce(DateName(Month, MoDate), 'Total') Mo,
Convert(varchar(11), Sum(Cnt)) + ' day' + CASE WHEN Sum(Cnt) = 1 THEN '' ELSE 's' END Descr
FROM Dys
GROUP BY MoDate
WITH ROLLUP
ORDER BY
Grouping(MoDate),
MoDate;
You could replace each occurance of ED_DISCHARGE_DATE with:
IsNull(ED_DISCHARGE_DATE,getdate())
This uses the current time whenever the discharge date is unavailable.