Reputation: 478
I am wondering why I cannot create the following T-SQL function:
CREATE FUNCTION DaysIncarceratedInYear
--Requires a Patient ID and a year
-- will return the number of days the patient was incarcerated for the year
--incarcerated is stored in a flowsheet
-- the FlowdataID are:
-- Incarceration Start Date: 'ZZZZZ00071
-- Incarceration End Date : 'ZZZZZ00072'
(
@PID varchar(10),
@YEAR int
)
RETURNS int
--DECLARE @PID varchar(10)
--DECLARE @YEAR int
--set @PID = 'ZZZZZ000L6'
--set @YEAR =2012
AS
BEGIN
declare @R int
SELECT @R = Numdays from (
;with startdates as
(
SELECT
dbo.View_PatientFlowValue.FlowValue_Value as val,
ROW_NUMBER() OVER(ORDER BY dbo.View_PatientFlowValue.FlowValue_Value) AS RowNumber
FROM dbo.View_PatientFlowValue
WHERE dbo.View_PatientFlowValue.FlowData_ID = 'ZZZZZ00071'
AND dbo.View_PatientFlowValue.FlowValue_RecordState<>1
AND Patient_ID = @PID
)
,enddates as
(
SELECT
dbo.View_PatientFlowValue.FlowValue_Value val,
ROW_NUMBER() OVER(ORDER BY dbo.View_PatientFlowValue.FlowValue_Value) AS RowNumber
FROM dbo.View_PatientFlowValue
WHERE dbo.View_PatientFlowValue.FlowData_ID = 'ZZZZZ00072'
AND dbo.View_PatientFlowValue.FlowValue_RecordState<>1
AND Person_ID = @PID
)
Select sum(DATEDIFF(d,CalcStart, CalcEnd)) as NumDays
from (
select
case
when DATEDIFF(d, cast(str(@YEAR*10000+1*100+1) as date), s.val) < 1 then '1/1/' + str(@YEAR)
else s.val
end As CalcStart,
ISNULL(e.Val, cast(str((@YEAR+1)*10000+1*100+1) as date)) as CalcEnd,
s.val as realstart, e.val as realend
FROM StartDates s
LEFT OUTER JOIN EndDates e ON s.RowNumber = e.RowNumber
) accountforyear
)
return @R
END
GO
It states there is incorrect syntax near ";" , but if I take the ";" out, it tells me there is incorrect syntax near the keyword "with". What is the proper syntax here?
This query works fine standalone.
Upvotes: 1
Views: 4207
Reputation: 16498
Define your CTEs before the query:
;with CTE_A( ColA, ColB)
as
(
select
ColA
, ColB
from
SomeTable
)
,CTE_B( ColA, ColC )
as
(
select
ColA
, ColC
from
SomeTable2
)
select
*
from
CTE_A a
inner join CTE_B b
on a.ColA = b.ColB
Upvotes: 0
Reputation: 37215
I've never seen a CTE as a subquery.
Try re-writing as
;
with startdates as
(
... copy everything
)
Select @R = sum(DATEDIFF(d,CalcStart, CalcEnd))
FROM ...
return @R
Upvotes: 3
Reputation: 1269873
You need to put the with
statement before the select
:
with startdates as
(
SELECT
dbo.View_PatientFlowValue.FlowValue_Value as val,
ROW_NUMBER() OVER(ORDER BY dbo.View_PatientFlowValue.FlowValue_Value) AS RowNumber
FROM dbo.View_PatientFlowValue
WHERE dbo.View_PatientFlowValue.FlowData_ID = 'ZZZZZ00071'
AND dbo.View_PatientFlowValue.FlowValue_RecordState<>1
AND Patient_ID = @PID
)
,enddates as
(
SELECT
dbo.View_PatientFlowValue.FlowValue_Value val,
ROW_NUMBER() OVER(ORDER BY dbo.View_PatientFlowValue.FlowValue_Value) AS RowNumber
FROM dbo.View_PatientFlowValue
WHERE dbo.View_PatientFlowValue.FlowData_ID = 'ZZZZZ00072'
AND dbo.View_PatientFlowValue.FlowValue_RecordState<>1
AND Person_ID = @PID
)
Select @R = sum(DATEDIFF(d,CalcStart, CalcEnd)) as NumDays
from (
select
case
when DATEDIFF(d, cast(str(@YEAR*10000+1*100+1) as date), s.val) < 1 then '1/1/' + str(@YEAR)
else s.val
end As CalcStart,
ISNULL(e.Val, cast(str((@YEAR+1)*10000+1*100+1) as date)) as CalcEnd,
s.val as realstart, e.val as realend
FROM StartDates s
LEFT OUTER JOIN EndDates e ON s.RowNumber = e.RowNumber
) accountforyear;
So, the @R =
goes in the select
after the with
. You don't need a subquery here, so I just added the assignment in.
Upvotes: 2