TSQL - 替换光标

时间:2018-04-18 09:01:51

标签: tsql sql-server-2012 cursor

我在数据库中找到了一个游标语句,我想替换它。

Declare @max_date datetime
Select @max_date = max(finished) From Payments
Declare @begin_date datetime = '2015-02-01'
Declare @end_of_last_month datetime 
While @begin_date <= @max_date
Begin
    SELECT @end_of_last_month = CAST(DATEADD(DAY, -1 , DATEFROMPARTS(YEAR(@begin_date),MONTH(@begin_date),1)) AS DATE) --AS end_of_last_month

    Insert Into @table(Customer, ArticleTypeID, ArticleType, end_of_month, month, year)
    Select Count(distinct (customerId)), prod.ArticleTypeID, at.ArticleType, @end_of_last_month, datepart(month, @end_of_last_month), datepart(year, @end_of_last_month)
    From Customer cust
    Inner join Payments pay ON pay.member_id = m.member_id
    Inner Join Products prod ON prod.product_id = pay.product_id
    Inner Join ArticleType at ON at.ArticleTypeID = prod.ArticleTypeID
    Where  @end_of_last_month between begin_date and expire_date
        and completed = 1
        Group by prod.ArticleTypeID, at.ArticleType
    order by prod.ArticleTypeID, at.ArticleType

    Set @begin_date = DATEADD(month, 1, @begin_date)
    End

它将实际Cursormonth中开始日期和到期日期的每月所有用户分组。

注意: 用户具有不同的付款类型,例如1个月,6个月等等。

是否可以重写代码 - 我的问题只是where子句的标识(在begin_date和expire_date之间@end_of_last_month) 我怎么能用连接或cte来处理这个?

1 个答案:

答案 0 :(得分:1)

首先需要的是numbers

使用所述Numbers表,您可以为&#34; end_of_Last_Month&#34;创建一个动态的日期列表。像这样

;WITH ctexAllDates
AS (
    SELECT  end_of_last_month = DATEADD(DAY, -1, DATEADD(MONTH, N.N -1, @begin_date))
    FROM
            dbo.Numbers N
    WHERE
            N.N <= DATEDIFF(MONTH, @begin_date, @max_date) + 1
)
select * FROM ctexAllDates

然后与您的查询结合起来

;WITH ctexAllDates
AS (
    SELECT  end_of_last_month = DATEADD(DAY, -1, DATEADD(MONTH, N.N -1, @begin_date))
    FROM
            dbo.Numbers N
    WHERE
            N.N <= DATEDIFF(MONTH, @begin_date, @max_date) + 1
)
INSERT INTO @table
(
      Customer
    , ArticleTypeID
    , ArticleType
    , end_of_month
    , month
    , year
)
SELECT
              COUNT(DISTINCT (customerId))
            , prod.ArticleTypeID
            , at.ArticleType
            , A.end_of_last_month
            , DATEPART(MONTH, A.end_of_last_month)
            , DATEPART(YEAR, A.end_of_last_month)
FROM
            Customer    cust
INNER JOIN  Payments    pay ON pay.member_id    = m.member_id
INNER JOIN  Products    prod ON prod.product_id = pay.product_id
INNER JOIN  ArticleType at ON at.ArticleTypeID  = prod.ArticleTypeID
LEFT JOIN ctexAllDates A ON     A.end_of_last_month BETWEEN begin_date AND expire_date
WHERE           completed   = 1
GROUP BY
              prod.ArticleTypeID
            , at.ArticleType
            , A.end_of_last_month
ORDER BY
              prod.ArticleTypeID
            , at.ArticleType;