WHOLE - 替换光标
TSQL - Replace 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 子句处的标识(@end_of_last_month
在 begin_date 和 expire_date 之间)
我如何使用连接或 cte 来处理这个问题?
您首先需要的是 numbers table
使用上述数字 table 您可以为 "end_of_Last_Month" 创建一个动态日期列表,就像这样
;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;
我在我们的数据库中发现了一个游标语句,我想替换它。
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 子句处的标识(@end_of_last_month
在 begin_date 和 expire_date 之间)
我如何使用连接或 cte 来处理这个问题?
您首先需要的是 numbers table
使用上述数字 table 您可以为 "end_of_Last_Month" 创建一个动态日期列表,就像这样
;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;