Sql server 使用CASE语句连接表,并基于CASE,然后选择一个最大值

Sql server 使用CASE语句连接表,并基于CASE,然后选择一个最大值,sql-server,sql-server-2012,Sql Server,Sql Server 2012,我想在4个条件下加入一个表,其中2个条件非常简单,另外2个条件更困难 前两项: PMCCONTRACTSTATUS.contracted=customunreportable.contracted PMCCONTRACTSTATUS.DATAAREAID=customunreporttable.DATAAREAID 第二点: 仅当表格PMCCONTRACTSTATUS中的FROMDATE低于表格CUSTAMOUNTREPORTTABLE中的PERIODSTART时 只有在这种情况下,才能选择最高

我想在4个条件下加入一个表,其中2个条件非常简单,另外2个条件更困难

前两项:

PMCCONTRACTSTATUS.contracted=customunreportable.contracted PMCCONTRACTSTATUS.DATAAREAID=customunreporttable.DATAAREAID

第二点:

仅当表格PMCCONTRACTSTATUS中的FROMDATE低于表格CUSTAMOUNTREPORTTABLE中的PERIODSTART时 只有在这种情况下,才能选择最高的行数。编辑:因为我想加入最接近PERIODSTART的[STATUS]

编辑:我制作了一个示例数据集,其中只包含解决问题所需的部分

CREATE TABLE PMCCONTRACTSTATUSLOG2 (
    ContractID nvarchar(20)
    ,[Status] int
    ,FromDate date
    ,RowNumber int
);

CREATE TABLE CUSTAMOUNTREPORTTABLE2 (
    ContractID nvarchar(20)
    ,PERIODSTART date
);

INSERT INTO PMCCONTRACTSTATUSLOG2 
(ContractID, [Status], FromDate, RowNumber)
VALUES
    ('HC1','1','01-01-2019','1'),
    ('HC1','2','01-02-2019','2'),
    ('HC1','1','01-04-2019','3'),
    ('HC2','1','01-04-2019','1'),
    ('HC2','2','01-05-2019','2'),
    ('HC3','4','01-01-2019','1'),
    ('HC3','2','01-02-2019','2'),
    ('HC3','1','01-07-2019','3'),
    ('HC3','2','01-09-2019','4'),
    ('HC4','2','01-08-2019','1'),
    ('HC4','3','01-07-2019','2'),
    ('HC5','1','01-02-2019','1');

INSERT INTO CUSTAMOUNTREPORTTABLE2
(ContractID, PERIODSTART)
VALUES
    ('HC1','01-01-2019'),
    ('HC2','01-01-2019'),
    ('HC3','01-01-2019'),
    ('HC5','01-01-2019'),
    ('HC1','01-02-2019'),
    ('HC3','01-02-2019'),
    ('HC5','01-02-2019'),
    ('HC1','01-03-2019'),
    ('HC3','01-03-2019'),
    ('HC5','01-03-2019'),
    ('HC1','01-04-2019'),
    ('HC2','01-04-2019'),
    ('HC3','01-04-2019'),
    ('HC5','01-04-2019'),
    ('HC1','01-05-2019'),
    ('HC2','01-05-2019'),
    ('HC3','01-05-2019'),
    ('HC5','01-05-2019');

SELECT * FROM PMCCONTRACTSTATUSLOG2
SELECT * FROM CUSTAMOUNTREPORTTABLE2
我尝试使用以下查询来联接PMCCONTRACTSTATUS表,我知道联接背后的逻辑,但我无法编写一个结合CASE WHEN+SELECT语句的联接

;WITH PMCCONTRACTSTATUS AS
(
SELECT
    CONTRACTID
    ,[STATUS]
    ,FROMDATE
    ,DATAAREAID
    ,ROW_NUMBER() OVER (PARTITION BY CONTRACTID ORDER BY FROMDATE ASC) RN
FROM PMCCONTRACTSTATUSLOG
WHERE [STATUS] <> 10 OR [STATUS] <> 5
)
SELECT 
    CART.CONTRACTID
    ,PMCCONTRACTSTATUS.CONTRACTID
    ,CART.ACCOUNTNUM
    ,CART.AMOUNTMSTTOTAL
    ,CART.PERIODSTART
    ,PMCCONTRACTSTATUS.FROMDATE
    ,CART.PERIODEND
    ,CART.NAME
    ,CART.PMCCONTRACTSTATUSWEIGHTED
    ,PMCCONTRACTSTATUS.[STATUS]
FROM CUSTAMOUNTREPORTTABLE CART
LEFT JOIN PMCCONTRACTSTATUS
    ON PMCCONTRACTSTATUS.CONTRACTID = CART.CONTRACTID
    AND PMCCONTRACTSTATUS.DATAAREAID = CART.DATAAREAID
    /*AND CASE WHEN PMCCONTRACTSTATUS.FROMDATE <= CART.PERIODSTART 
        THEN (SELECT MAX(PMCCONTRACTSTATUSLOG.RN) FROM PMCCONTRACTSTATUSLOG)*/

有什么建议吗?

这个答案是基于我的理解,可能缺少一些部分:

首先,我试着加入你在CTE中的三个先决条件。然后我根据两个日期之间的日期差异创建一个行号

告诉我这是否有帮助:

;WITH 
CTE AS (
SELECT 
    CART.CONTRACTID
    ,CART.ACCOUNTNUM
    ,CART.AMOUNTMSTTOTAL
    ,CART.PERIODSTART
    ,PMCCONTRACTSTATUSLOG.FROMDATE
    ,CART.PERIODEND
    ,CART.NAME
    ,CART.PMCCONTRACTSTATUSWEIGHTED
    ,PMCCONTRACTSTATUSLOG.[STATUS]
    ,ROW_NUMBER() OVER (PARTITION BY CART.CONTRACTID,CART.DATAAREAID ORDER BY DATEDIFF(second,FROMDATE,PERIODSTART) ASC) RN
FROM CUSTAMOUNTREPORTTABLE CART
LEFT JOIN PMCCONTRACTSTATUSLOG
    ON PMCCONTRACTSTATUSLOG.CONTRACTID = CART.CONTRACTID
    AND PMCCONTRACTSTATUSLOG.DATAAREAID = CART.DATAAREAID
    AND PMCCONTRACTSTATUSLOG.FROMDATE <= CART.PERIODSTART 
WHERE [STATUS] NOT IN (5,10)
)
SELECT 
    CONTRACTID
    ,ACCOUNTNUM
    ,AMOUNTMSTTOTAL
    ,PERIODSTART
    ,FROMDATE
    ,PERIODEND
    ,NAME
    ,PMCCONTRACTSTATUSWEIGHTED
    ,[STATUS]
FROM CTE
WHERE RN = 1

我认为你应该用外接而不是左接

;WITH PMCCONTRACTSTATUS AS
(
SELECT
    CONTRACTID
    ,[STATUS]
    ,FROMDATE
    ,DATAAREAID
    ,ROW_NUMBER() OVER (PARTITION BY CONTRACTID ORDER BY FROMDATE ASC) RN
FROM PMCCONTRACTSTATUSLOG
WHERE [STATUS] <> 10 OR [STATUS] <> 5
)
SELECT 
    CART.CONTRACTID
    ,PMCCONTRACTSTATUS.CONTRACTID
    ,CART.ACCOUNTNUM
    ,CART.AMOUNTMSTTOTAL
    ,CART.PERIODSTART
    ,MAX_PMCCONTRACTSTATUS.FROMDATE
    ,CART.PERIODEND
    ,CART.NAME
    ,CART.PMCCONTRACTSTATUSWEIGHTED
    ,MAX_PMCCONTRACTSTATUS.[STATUS]
FROM CUSTAMOUNTREPORTTABLE CART
OUTER APPLY (select top 1 *
            from PMCCONTRACTSTATUS
            where PMCCONTRACTSTATUS.CONTRACTID = CART.CONTRACTID
                    AND PMCCONTRACTSTATUS.DATAAREAID = CART.DATAAREAID
                    AND PMCCONTRACTSTATUS.FROMDATE <= CART.PERIODSTART
                    ORDER BY PMCCONTRACTSTATUSLOG.RN DESC) as MAX_PMCCONTRACTSTATUS

样本数据和预期结果将帮助我们在这里帮助您。您确定只想按construcd而不是DATAAREAID进行分区吗?据我所知,您试图获取的合同状态日志的起始日期与相同合同和数据区域的起始日期最接近?我说的对吗?确实是我在尝试的。DataAreaID是一个列,在PMCCONTRACTSTATUSLOG中,该列的值始终为“1”,因此在本例中不太有趣。但我将在这个问题中加入一个数据集,使其更容易回答。包括示例数据集,复制粘贴准备用于SQLThis不知何故没有起作用。我立即注意到,我的165100行减少到21000行。我现在确实包含了一个数据集以使其可复制。经过仔细研究后,这个查询就像一个符咒。它比其他人的外部应用建议更有效,因为外部应用需要2小时才能完成查询,并且在1分钟内完成。