具有多个条件的复杂查询

Complex query with multiple conditions

标题的 'complex' 部分可能是主观的,但对我来说,它相当复杂。

我有一个名为 Contracts (C)FinancialYears (FY) 的 table。如果满足特定状态,合同将有多个财政年度(每年一个),自动创建(例如,取消的合同不会获得新的财政年度记录,但批准的合同会)。 FY 每年都有一个特定的状态。例如:

--------------------FinancialYears-------------------
ContractID: 1          | 1          | 1
StatusID:   2          | 3          | 5
dStart:     01-01-2012 | 01-01-2013 | 01-01-2014
dEnd:       31-12-2012 | 31-12-2013 | 31-12-2014
Year:       2012       | 2013       | 2014
-----------------------------------------------------
(For example: StatusID (2, 3, 5), (Proposed, Approved, Cancelled))

现在假设用户想知道此时有多少合同被批准,那么查询应该查看合同的最近财政年度,这就是我遇到的困难与.

我必须编写一个执行以下操作的查询:

SELECT *
FROM Contracts C
INNER JOIN FinancialYears FY ON FY.ContractID = C.ContractID
WHERE StatusID = X AND (dStart < GETDATE() AND dEnd > GETDATE()) 
// This would search on the financial year of the contract which has its valid
period in-between today.

但是因为例如取消的合同在下一年没有新的财政年度,我今天永远无法查询2014年取消的合同,所以我需要调整以下条件以以某种方式查询:

// IF (dStart < GETDATE() AND dEnd > GETDATE()) RETURNS 0, THEN DO INSTEAD:
SELECT TOP 1 
//
WHERE (dEnd < GETDATE) 
ORDER BY ENDDATE DESC
// With other words: if there is no ongoing financial year between the given time interval,
then select the most recent financial year in the past.

有人能帮我吗?

谢谢。

如果我没记错的话,你只需要筛选当前日期介于已批准合同的开始日期和结束日期之间的合同即可。

Here's a demo SQL Fiddle

MS SQL 服务器架构设置:

CREATE TABLE FinancialYearContracts
    ([ContractID] int, [StatusID] int, [dStart] datetime, [dEnd] datetime, [Year] int)
;

INSERT INTO FinancialYearContracts
    ([ContractID], [StatusID], [dStart], [dEnd], [Year])
VALUES
    (1, 2, '2012-01-01 00:00:00', '2012-12-31 00:00:00', 2012),
    (1, 3, '2013-01-01 00:00:00', '2013-12-31 00:00:00', 2013),
    (1, 5, '2014-01-01 00:00:00', '2014-12-31 00:00:00', 2014),
    (2, 2, '2013-01-01 00:00:00', '2013-12-31 00:00:00', 2013),
    (2, 3, '2014-01-01 00:00:00', '2014-12-31 00:00:00', 2014),
    (2, 3, '2015-01-01 00:00:00', '2015-12-31 00:00:00', 2015),
    (3, 2, '2014-01-01 00:00:00', '2014-12-31 00:00:00', 2014),
    (3, 3, '2015-01-01 00:00:00', '2015-12-31 00:00:00', 2015),
    (4, 2, '2014-01-01 00:00:00', '2014-12-31 00:00:00', 2014),
    (5, 2, '2013-01-01 00:00:00', '2013-12-31 00:00:00', 2013),
    (5, 3, '2014-01-01 00:00:00', '2014-12-31 00:00:00', 2014),
    (5, 3, '2015-01-01 00:00:00', '2015-12-31 00:00:00', 2015),
    (6, 2, '2013-01-01 00:00:00', '2013-12-31 00:00:00', 2012),
    (6, 3, '2014-01-01 00:00:00', '2014-12-31 00:00:00', 2013),
    (6, 5, '2015-01-01 00:00:00', '2015-12-31 00:00:00', 2014)
;

查询生成结果:

declare @DateFilter as datetime = GETDATE()
declare @Status as int = 3


SELECT * 
FROM FinancialYearContracts
WHERE @DateFilter BETWEEN dStart AND dEnd AND StatusID = @Status

Results:

| CONTRACTID | STATUSID |                         DSTART |                            DEND | YEAR |
|------------|----------|--------------------------------|---------------------------------|------|
|          2 |        3 | January, 01 2015 00:00:00+0000 | December, 31 2015 00:00:00+0000 | 2015 |
|          3 |        3 | January, 01 2015 00:00:00+0000 | December, 31 2015 00:00:00+0000 | 2015 |
|          5 |        3 | January, 01 2015 00:00:00+0000 | December, 31 2015 00:00:00+0000 | 2015 |

根据我整理的示例数据,这显示了当前处于已批准状态的合同。

这是一个快速模型:

SELECT *
FROM Contracts C
cross apply (
select top 1 ContractID 
from FinancialYears where dStart < GETDATE() 
order by dEnd desc
) F on C.ConractID = F.ContractID

但您可能需要一些额外的条件来查找所有合同,例如客户代码或其他内容。