具有多个条件的复杂查询

时间:2015-02-06 09:42:58

标签: sql sql-server tsql

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

我有一个名为Contracts (C)FinancialYears (FY)的表格。如果满足特定状态,合同将具有多个财务年度(每年一个),自动创建(例如,取消的合同不会获得新的财务年度记录,但已批准的合同将会生效)。它是每年具有特定地位的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.

有人可以帮助我吗?

谢谢。

2 个答案:

答案 0 :(得分:1)

如果我没有弄错的话,您只需要过滤当前日期在合同的开始日期和结束日期之间的合同。

Here's a demo SQL Fiddle

MS SQL Server架构设置

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 |

这表示根据我放在一起的样本数据,目前处于批准状态的合同。

答案 1 :(得分:1)

这是一个快速模拟:

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

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