在我的表中,我有两列:
leasecontract.[Contract Activation Date]
leasecontract.[Contract Ending Date]
对于这两列,我想生成一个表格,例如:
因此第一行的查询可以是(新合同):
SELECT
COUNT(leasecontract.Id) AS total,
YEAR(leasecontract.[Contract Activation Date]) AS jaar
FROM
leasecontract
GROUP BY
YEAR(leasecontract.[Contract Activation Date])
但有没有办法对中间行做同样的事情?显示按年份在1个查询中分组的有效合同。谢谢!
SQL版本是2008
答案 0 :(得分:2)
我会用三个常用的表格表达式来完成这个 每个列一个,您要选择。然后使用年份将它们连接在一起。
我不确定我是否正确理解了有关合同状态(新的,有效的和已关闭的)的条件。但是你可以很容易地调整每个commom表表达式中的WERE
- 条件。
WITH newContracts
AS ( SELECT total = COUNT(l.Id) ,
[Year] = YEAR(GETDATE())
FROM leasecontract l
WHERE GETDATE() < l.[Contract Activation Date]
GROUP BY YEAR(GETDATE())
),
activeContracts
AS ( SELECT total = COUNT(l.Id) ,
[Year] = YEAR(l.[Contract Activation Date])
FROM leasecontract l
WHERE GETDATE() >= l.[Contract Activation Date]
AND GETDATE() < l.[Contract Ending Date]
GROUP BY YEAR(l.[Contract Activation Date])
),
closedContracts
AS ( SELECT total = COUNT(l.Id) ,
[Year] = YEAR(l.[Contract Ending Date])
FROM leasecontract l
WHERE GETDATE() >= l.[Contract Ending Date]
GROUP BY YEAR(l.[Contract Ending Date])
)
SELECT n.[Year] ,
n.total AS [New contracts] ,
a.total AS [Active contracts] ,
c.total AS [Closed contracts]
FROM newContracts n
JOIN activeContracts a ON n.[Year] = a.[Year]
JOIN closedContracts c ON a.[Year] = c.[Year]
答案 1 :(得分:1)
之前从未做过递归CTE。但这是一个学习的好地方。所以,下面的那个应该有效。如果没有结束日期的合同,它将显示为&#34;活动&#34;在其开始日期之后的所有列出年份。假设您的SQL Server版本是2008或更高版本,我认为。
递归可能没有必要,但理论上只是从开始和结束日期开始DISTINCT年,有可能在没有新合同被打开的闰年,或旧的合同被关闭,而它们仍然是活性。这样,即使闰年也会被包括在内,加上最小/最大可能会超过表现性能的DISTINCT / GROUP BY日期。
;WITH DateLimits AS
-- Fetching absolute MIN and MAX date
(SELECT MinDate, CASE WHEN MaxDate < MaxDateCheck THEN MaxDateCheck ELSE MaxDate END AS MaxDate
FROM
(SELECT MIN([Contract Activation Date]) MinDate
, MAX([Contract Ending Date]) MaxDate
, MAX([Contract Activation Date]) MaxDateCheck
FROM LEASECONTRACT) SRC)
-- Creating all years between MIN start and MAX endtime
, CTESeq AS
(SELECT YEAR(MinDate) [Year]
FROM DateLimits
UNION ALL
SELECT [Year]+1
FROM CTESeq
JOIN DateLimits ON 1=1
WHERE [Year] < YEAR(MaxDate))
-- Forming the results based on CTESeq above
SELECT *
FROM CTESeq CTE
OUTER APPLY (SELECT COUNT(*) [New Contracts] FROM LEASECONTRACT WHERE YEAR([Contract Activation Date]) = CTE.Year) OAStarts
OUTER APPLY (SELECT COUNT(*) [Active Contracts] FROM LEASECONTRACT
WHERE CTE.Year BETWEEN YEAR([Contract Activation Date]) AND ISNULL(YEAR([Contract Ending Date]),CTE.Year)) OAActive
OUTER APPLY (SELECT COUNT(*) [Closed Contracts] FROM LEASECONTRACT WHERE YEAR([Contract Ending Date]) = CTE.Year) OAEnds
ORDER BY [Year] ASC
OPTION (MAXRECURSION 100);
编辑:添加了一个检查,以确定MAX endtime实际上小于MAX starttime。
编辑2 :神圣的,NePh的多个CTE查询示例非常棒。不知道你可以做到这一点。我通过他的示例将我的响应更改为单个查询,而是使用额外的CTE选择替换先前的变量。