我有一个T-SQL报价表,需要能够计算过去几个月中有多少报价处于未结状态。
我必须使用的日期是' Add_Date
'时间戳和' Update_Date
'时间戳。将报价添加到&{39; Closed_Status
' ' 1
'它无法再更新。因此,' Update_Date
'有效地成为Closed_Status
时间戳。
我被卡住了,因为我无法弄清楚如何选择在特定月份开放的所有公开引语。
以下是一些示例记录:
Quote_No Add_Date Update_Date Open_Status Closed_Status
001 01-01-2016 NULL 1 0
002 01-01-2016 3-1-2016 0 1
003 01-01-2016 4-1-2016 0 1
期望的结果是:
Year Month Open_Quote_Count
2016 01 3
2016 02 3
2016 03 2
2016 04 1
我已经在这个问题上遇到了心理障碍,我试图进行一些case when
过滤,但我似乎无法解决这个难题。理想情况下,我不会在日期中进行硬编码,因为这需要多年,我不想在编写之后保持这一点。
提前感谢您的帮助。
答案 0 :(得分:6)
你这个月是这样做的。因此,我想到了三种选择:
left join
。让我展示一下:
with n as (
select row_number() over (order by (select null)) - 1 as n
from master..spt_values
)
select format(dateadd(month, n.n, q.add_date), 'yyyy-MM') as yyyymm,
count(*) as Open_Quote_Count
from quotes q join
n
on (closed_status = 1 and dateadd(month, n.n, q.add_date) <= q.update_date) or
(closed_status = 0 and dateadd(month, n.n, q.add_date) <= getdate())
group by format(dateadd(month, n.n, q.add_date), 'yyyy-MM')
order by yyyymm;
这假设每个月至少有一个开放记录。这似乎是合理的。
答案 1 :(得分:0)
您可以使用datepart
来提取日期的部分内容,例如:
select datepart(year, add_date) as 'year',
datepart(month, date_date) as 'month',
count(1)
from theTable
where open_status = 1
group by datepart(year, add_date), datepart(month, date_date)
注意:这会计入起始月份,主要用于显示datepart
的使用情况。
答案 2 :(得分:0)
更新为误解了初始请求。
考虑以下测试数据:
DECLARE @test TABLE
(
Quote_No VARCHAR(3),
Add_Date DATE,
Update_Date DATE,
Open_Status INT,
Closed_Status INT
)
INSERT INTO @test (Quote_No, Add_Date, Update_Date, Open_Status, Closed_Status)
VALUES ('001', '20160101', NULL, 1, 0)
, ('002', '20160101', '20160301', 0, 1)
, ('003', '20160101', '20160401', 0, 1)
这是一个递归解决方案,它不依赖于系统表,但也表现得更差。正如我们所说的月份和年份组合一样,递归次数不会超额。
;WITH YearMonths AS
(
SELECT YEAR(MIN(Add_Date)) AS [Year]
, MONTH(MIN(Add_Date)) AS [Month]
, MIN(Add_Date) AS YMDate
FROM @test
UNION ALL
SELECT YEAR(DATEADD(MONTH,1,YMDate))
, MONTH(DATEADD(MONTH,1,YMDate))
, DATEADD(MONTH,1,YMDate)
FROM YearMonths
WHERE YMDate <= SYSDATETIME()
)
SELECT [Year]
, [Month]
, COUNT(*) AS Open_Quote_Count
FROM YearMonths ym
INNER JOIN @test t
ON (
[Year] * 100 + [Month] <= CAST(FORMAT(t.Update_Date, 'yyyyMM') AS INT)
AND t.Closed_Status = 1
)
OR (
[Year] * 100 + [Month] <= CAST(FORMAT(SYSDATETIME(), 'yyyyMM') AS INT)
AND t.Closed_Status = 0
)
GROUP BY [Year], [Month]
ORDER BY [Year], [Month]
声明更长,更具可读性,并列出了迄今为止的所有年/月组合。
查看Date and Time Data Types and Functions的SQL-Server 2008+