Sql r如果我遇到无法正确优化CTE的问题(有很多这样的情况)。对于带有常数的CTE,我更喜欢上面的表,而不是临时表100:1。正如我在评论中所说,我有时也会因为声明变量而受到批评,但在生产代码中,我可能会这样做,而不是让CTE调用d…没有人不想看到DECLAR

Sql r如果我遇到无法正确优化CTE的问题(有很多这样的情况)。对于带有常数的CTE,我更喜欢上面的表,而不是临时表100:1。正如我在评论中所说,我有时也会因为声明变量而受到批评,但在生产代码中,我可能会这样做,而不是让CTE调用d…没有人不想看到DECLAR,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,r如果我遇到无法正确优化CTE的问题(有很多这样的情况)。对于带有常数的CTE,我更喜欢上面的表,而不是临时表100:1。正如我在评论中所说,我有时也会因为声明变量而受到批评,但在生产代码中,我可能会这样做,而不是让CTE调用d…没有人不想看到DECLARE@dt DATE=CURRENT\u TIMESTAMP只是在以后的查询中使用-他们希望我只把常量放进去,避免“额外的代码行”(即使有转换和/或变量重复多次)。这没什么大不了的,只是我注意到有一些东西被反复地重复着。@Aaron_Bertra


r如果我遇到无法正确优化CTE的问题(有很多这样的情况)。对于带有常数的CTE,我更喜欢上面的表,而不是临时表100:1。正如我在评论中所说,我有时也会因为声明变量而受到批评,但在生产代码中,我可能会这样做,而不是让CTE调用
d
…没有人不想看到
DECLARE@dt DATE=CURRENT\u TIMESTAMP
只是在以后的查询中使用-他们希望我只把常量放进去,避免“额外的代码行”(即使有转换和/或变量重复多次)。这没什么大不了的,只是我注意到有一些东西被反复地重复着。@Aaron_Bertrand谢谢你的编辑。这对我来说更清楚了。是的,这确实满足了我的需要。你说的w[start]是指w[dt]?是的,更正了,对不起。我最初计划使用本周的[开始],并在飞行中进行了更改。是否有特殊原因使用CTE而不是临时表?当我需要做一些我想利用的初步操作/计算时,我通常使用临时表……我想知道是否有什么好的理由使用CTE代替它们。谢谢。这只是一个语句,而不是一堆不同的步骤,如果我不需要创建一个临时表来写4行,为什么还要麻烦呢?如果我确实需要首先对行进行大量处理,或者遇到CTE无法正确优化的问题(有很多这样的情况),我通常会返回到#temp表。对于带有常数的CTE,我更喜欢上面的表,而不是临时表100:1。正如我在评论中所说,我有时也会因为声明变量而受到批评,但在生产代码中,我可能会这样做,而不是让CTE调用
d
…没有人不想看到
DECLARE@dt DATE=CURRENT\u TIMESTAMP
只是在以后的查询中使用-他们希望我只把常量放进去,避免“额外的代码行”(即使有转换和/或变量重复多次)。这没什么大不了的,只是我注意到有些东西被反复地重复着。
id      hired_date       term_date
3        07/1/2011        09/01/2011
4        07/18/2011        NULL    (NULL means still active) 
5        01/20/2009       08/23/2011
6        05/30/2011       8/22/2011
7        7/20/2011        7/23/2011
Week ending     Terminated employees hired within past 90 days
09/03/2011        2   --(id 3,7)
8/27/2011         2   --(id 6,7)
..
..
select wk.ninety_end, count(h.id)
FROM @weeks wk
LEFT JOIN all_termed_employees h 
    ON h.hire_date <= wk.ninety_end and h.hire_date >= wk.ninety_begin
          and .termination_date <= wk.ninety_end AND h.termination_date >= wk.ninety_begin
ORDER BY d.id
GROUP BY wk.ninety_end
; WITH EMP (id, hired_date, term_date) AS
(
    select 3, CAST('2011-07-01' AS datetime), CAST('2011-09-01' AS datetime)
    union all select 4, '2011-06-18', null
    union all select 5, '01/20/2009','08/23/2011'
    union all select 6, '05/30/2011','8/22/2011'
    union all select 7, '7/20/2011','7/23/2011'
)
, PAST_FOUR_WEEKS (period, period_rank) AS
(
    -- magic goes here to determine end of week
    SELECT CURRENT_TIMESTAMP, 1
    UNION ALL SELECT dateadd(week, -1, CURRENT_TIMESTAMP) , 2
    UNION ALL SELECT dateadd(week, -2, CURRENT_TIMESTAMP) , 3
    UNION ALL SELECT dateadd(week, -3, CURRENT_TIMESTAMP) , 4
)
, HIRED_TERMED_DIFF AS
(
    SELECT
        *
    ,   DATEDIFF(d, E.hired_date, coalesce(E.term_date, '9999-12-31T23:59:59.997')) AS duration
    ,   CASE WHEN DATEDIFF(d, E.hired_date, coalesce(E.term_date, '9999-12-31T23:59:59.997')) < 91 THEN 1 ELSE 0 END AS threshold_met
    FROM
        EMP E 
)
SELECT
    PFW.period
,   SUM(HTD.threshold_met) AS [Terminated employees hired within past 90 days]
FROM 
    PAST_FOUR_WEEKS PFW
    LEFT OUTER JOIN
        HIRED_TERMED_DIFF HTD
        ON HTD.hired_date BETWEEN DATEADD(day, -90, PFW.period) AND PFW.period
GROUP BY
    PFW.period
ORDER BY
    1 DESC
,   2
period                    Terminated employees hired within past 90 days
2011-09-01 14:46:29.243   2
2011-08-25 14:46:29.243   3
2011-08-18 14:46:29.243   3
2011-08-11 14:46:29.243   3
;WITH n(n) AS 
      -- just 4 rows - makes it easy to extend to 5 weeks, 6 weeks, etc.
      ( SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 ),

d(dt) AS
      -- single row with the end of the current week
      -- this could be a variable but I get a lot of flack for not inlining
      ( SELECT dt = CONVERT(DATE, DATEADD(DAY, 
          7-DATEPART(WEEKDAY, CURRENT_TIMESTAMP), CURRENT_TIMESTAMP))),

w(dt) AS 
      -- get the end of each week based on the rows in n
      ( SELECT DATEADD(WEEK, -n.n, d.dt) FROM n CROSS JOIN d )

SELECT 
    w.dt, SUM(CASE 
    WHEN e.term_date >= DATEADD(DAY, -90, w.dt) 
    AND e.term_date  <  DATEADD(DAY, 1,   w.dt) 
    AND e.hired_date >= DATEADD(DAY, -90, w.dt) 
    AND e.hired_date <  DATEADD(DAY, 1,   w.dt)  
    THEN 1 ELSE 0 END)
FROM dbo.Employees AS e
CROSS JOIN w
GROUP BY w.dt
ORDER BY w.dt DESC;