带有'with'子句的T SQL函数

时间:2013-03-28 18:39:54

标签: sql tsql function sql-server-2008-r2

我想知道为什么我不能创建以下T-SQL函数:

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

它声明“;”附近的语法不正确,但如果我拿“;” out,它告诉我关键字“with”附近有不正确的语法。这里的语法是什么?

此查询可以很好地独立运行。

3 个答案:

答案 0 :(得分:3)

我从未见过CTE作为子查询。

尝试重写为

;
with startdates as
(
   ... copy everything

)
Select @R = sum(DATEDIFF(d,CalcStart, CalcEnd))
FROM ...

return @R

答案 1 :(得分:2)

您需要将with语句放在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;

因此,@R =select with之后进入{{1}} 。这里不需要子查询,所以我只是添加了赋值。

答案 2 :(得分:0)

在查询之前定义您的CTE:

;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