如何将select子句中的子查询重写为CTE

时间:2014-01-10 17:05:54

标签: sql sql-server subquery common-table-expression

我需要重写SQL查询,以便它不包含任何子查询,因为将要执行它的第三方程序的要求。但是我只知道一点SQL,到目前为止还没有找到任何帮助我的东西。

我需要重写的子查询的一个例子是:

SELECT
DateAdd(millisecond
, ISnull((select RawOffset 
from tbl_lms_TimeZoneData 
where TimeZone_FK = (act.TimeZoneFK) ),0) 

, DateAdd(millisecond
, ISnull((select Offset 
from tbl_lms_ConvertTimeZoneData 
where TimeZone_FK = (act.TimeZoneFK) 
and act.StartDt between StartDate and EndDate),0) , act.StartDt)) 
as N'Activity Start Date'

FROM
etc...

act在FROM子句中定义。

查询按原样运行,但是我用CTE替换子查询的任何尝试都会破坏它。

在这种情况下是否可以替换子查询?

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

你确定你甚至需要CTE吗?看起来你可以简单地使用外连接。

SELECT DateAdd(millisecond, 
               ISnull(tzd.RawOffset,0),
                      DateAdd(millisecond,
                              ISnull(ctzd.Offset,0),
                              Act.StartDt)) as N'Activity Start Date'
    FROM Act
        LEFT OUTER JOIN tbl_lms_TimeZoneData tzd
            ON tzd.TimeZone_FK = act.TimeZoneFK
        LEFT OUTER JOIN tbl_lms_ConvertTimeZoneData ctzd
            ON ctzd.TimeZone_FK = act.TimeZoneFK
            AND act.StartDt between ctzd.StartDate and ctzd.EndDate

不确定Act在子查询中做了什么条件来自tbl_lms_ConvertTimeZoneData,但我保留了它。

UPD:我猜,Start和End实际上属于tbl_lms_ConvertTimeZoneData。修改了查询。

答案 1 :(得分:0)

如果您最终不得不使用CTE,那么您应该能够像这样做:

WITH cte_TimeZoneData AS (
    SELECT  RawOffset, TimeZone_FK
    FROM    dbo.tbl_lms_TimeZoneData ),
cte_ConvertTimeZoneData AS (
    SELECT  Offset, TimeZone_FK, StartDate, EndDate
    FROM    dbo.tbl_lms_ConvertTimeZoneData )
SELECT  [Activity Start Date] = DATEADD( MILLISECOND,
            ISNULL( tzd.RawOffset, 0 ), DATEADD( MILLISECOND,
            ISNULL( ctzd.Offset, 0 ), act.StartDt ) )
FROM    dbo.Act act
LEFT JOIN cte_TimeZoneData tzd
    ON  act.TimeZoneFK = tzd.TimeZone_FK
LEFT JOIN cte_ConvertTimeZoneData ctzd
    ON  act.TimeZoneFK = ctzd.TimeZone_FK
    AND act.StartDt >= ctzd.StartDate
    AND act.StartDt < ctzd.EndDate;