Sql server 需要解决多个条件的复杂where子句问题

Sql server 需要解决多个条件的复杂where子句问题,sql-server,where-clause,ssms-2017,Sql Server,Where Clause,Ssms 2017,我有一个正在进行的项目,我正在使用左连接将几个表组合成一个表,以便dbo.spi是主要的。我的问题来自where子句和提取任何带有null的内容 为了让它显示在结果中,需要满足几个标准。我的问题是,无论我如何编写where子句,某些标准似乎会破坏其他标准。我知道这和我的订单有关,但我不知道是什么。我的标准如下 我尝试过许多不同的命令,但是无论我在某个时候做什么,where子句中的某些标准似乎开始被忽略。对不起,时间太长了,请提前感谢大家 Part 1: M.knum must be Null D

我有一个正在进行的项目,我正在使用左连接将几个表组合成一个表,以便dbo.spi是主要的。我的问题来自where子句和提取任何带有null的内容

为了让它显示在结果中,需要满足几个标准。我的问题是,无论我如何编写where子句,某些标准似乎会破坏其他标准。我知道这和我的订单有关,但我不知道是什么。我的标准如下

我尝试过许多不同的命令,但是无论我在某个时候做什么,where子句中的某些标准似乎开始被忽略。对不起,时间太长了,请提前感谢大家

Part 1:
M.knum must be Null
D.Knum must be null
O.knum must be null
E.Knum must be null
st.customer_id must be Null

Part 2:
IF c.pbs#freq is A and c.pbs#days#delq <= 716 - Show in results
IF c.pbs#freq is E and c.pbs#days#delq <= 1446 - Show in results
IF c.pbs#freq is O and c.pbs#days#delq <= 1081 - Show in results
IF c.pbs#freq is null - Show in results

Part 3: 
i.date >= 5/1/2019 - Show in results 
i.date is Null - Show in results

Part 4:
p.d30 is <= 6 or null - Show in results
p.d60 is <= 1 or null - Show in results
p.d90 is <= 0 or null - Show in results

Part 5:
p.pmts_Made >= 12 or p.pmts_made is null - Show in results

我试图对您的查询进行排序,但仍然有许多令人困惑的事情,因为我不知道数据库的结构

我认为您的主要查询应该如下所示:

SELECT  s.knum,m.knum as M_knum, 
        d.knum as D_knum, 
        o.knum as O_knum, 
        e.knum as E_knum, 
        s.customer_id, 
        st.customer_id as ST_Customer_id, 
        s.fdd, s.[status], s.[state], 
    (
        SELECT max(HighTrw) 
        FROM (
                VALUES (trw1), (trw2), (trw3)) as Value(HighTrw)
    ) as high_trw, 
    i.knum as Issued, 
    ISNULL(i.date, '1980-01-01') as Issued_Date, 
    c.PBS#DISP as MF_Disp, 
    c.LN#DISP as LN_Disp,
    c.PBS#DAYS#DELQ as MF_Delq, 
    c.PBS#FREQ as MF_Freq, 
    c.LN#CURR#BAL as LN_Bal, 
    c.LN#NPDD as NPDD, 
    p.PMTS_Made as Pmts_Made, 
    p.D30, p.D60, p.D90
From dbo.SPI S 
LEFT OUTER JOIN dbo.combined C on s.knum = c.knum
Left outer join dbo.payments P on s.knum = p.knum 
Left join dbo.dvn D on s.knum = d.knum AND d.knum is null
Left join dbo.exclusion E on s.knum = e.knum AND e.knum IS null
left join dbo.issued I  on s.knum = i.knum
left join dbo.outfield O on s.knum = o.knum AND o.knum is null
 left join dbo.spi_tours ST on s.customer_id = st.customer_id AND st.customer_id IS Null
 left join dbo.magna M on s.knum = m.knum AND m.knum is null
 WHERE
    (   (c.pbs#freq = 'A' and c.pbs#days#delq <= 716 ) or (c.pbs#freq = 'E' and c.pbs#days#delq <= 1446) or (c.pbs#freq = 'O' and c.pbs#days#delq <= 1081) OR c.pbs#freq is null ) 
AND ( (CONVERT(DATE,i.[date]) >= CONVERT(DATE,'2019-05-01') or i.[date] is null) )
AND ( (CAST(p.d30 AS INT) <= 6 or p.d30 is null) AND (CAST(p.d60 AS INT) <= 1 or p.d60 is null) AND (CAST(p.d90 AS INT) <= 0 or p.d90 is null) )

AND (CAST(p.PMTS_Made AS INT) >= 12 or p.pmts_made is null)

我建议首先运行上面的部分并查看结果,希望您的所有过滤器都能正常工作,因为我在join上有一些过滤器,其中一些过滤器是我用适当的转换进行格式化的,还有一些过滤器是我试图放进适当的大括号中的

我试图对您的查询进行排序,但仍然有许多令人困惑的事情,因为我不知道数据库的结构

我认为您的主要查询应该如下所示:

SELECT  s.knum,m.knum as M_knum, 
        d.knum as D_knum, 
        o.knum as O_knum, 
        e.knum as E_knum, 
        s.customer_id, 
        st.customer_id as ST_Customer_id, 
        s.fdd, s.[status], s.[state], 
    (
        SELECT max(HighTrw) 
        FROM (
                VALUES (trw1), (trw2), (trw3)) as Value(HighTrw)
    ) as high_trw, 
    i.knum as Issued, 
    ISNULL(i.date, '1980-01-01') as Issued_Date, 
    c.PBS#DISP as MF_Disp, 
    c.LN#DISP as LN_Disp,
    c.PBS#DAYS#DELQ as MF_Delq, 
    c.PBS#FREQ as MF_Freq, 
    c.LN#CURR#BAL as LN_Bal, 
    c.LN#NPDD as NPDD, 
    p.PMTS_Made as Pmts_Made, 
    p.D30, p.D60, p.D90
From dbo.SPI S 
LEFT OUTER JOIN dbo.combined C on s.knum = c.knum
Left outer join dbo.payments P on s.knum = p.knum 
Left join dbo.dvn D on s.knum = d.knum AND d.knum is null
Left join dbo.exclusion E on s.knum = e.knum AND e.knum IS null
left join dbo.issued I  on s.knum = i.knum
left join dbo.outfield O on s.knum = o.knum AND o.knum is null
 left join dbo.spi_tours ST on s.customer_id = st.customer_id AND st.customer_id IS Null
 left join dbo.magna M on s.knum = m.knum AND m.knum is null
 WHERE
    (   (c.pbs#freq = 'A' and c.pbs#days#delq <= 716 ) or (c.pbs#freq = 'E' and c.pbs#days#delq <= 1446) or (c.pbs#freq = 'O' and c.pbs#days#delq <= 1081) OR c.pbs#freq is null ) 
AND ( (CONVERT(DATE,i.[date]) >= CONVERT(DATE,'2019-05-01') or i.[date] is null) )
AND ( (CAST(p.d30 AS INT) <= 6 or p.d30 is null) AND (CAST(p.d60 AS INT) <= 1 or p.d60 is null) AND (CAST(p.d90 AS INT) <= 0 or p.d90 is null) )

AND (CAST(p.PMTS_Made AS INT) >= 12 or p.pmts_made is null)

我建议首先运行上面的部分并查看结果,希望您的所有过滤器都能正常工作,因为我在join上有一些过滤器,其中一些过滤器是我用适当的转换进行格式化的,还有一些过滤器是我试图放进适当的大括号中的

我相信这会满足您的需求。请注意,您从where子句中排除了high_trw value检查,因此我将它们重新添加到:

SELECT s.knum,
    m.knum AS M_knum,
    d.knum AS D_knum,
    o.knum AS O_knum,
    e.knum AS E_knum,
    s.customer_id,
    st.customer_id AS ST_Customer_id,
    s.fdd,
    s.STATUS,
    s.STATE,
    (
        SELECT max(HighTrw)
        FROM (
            VALUES (trw1),
                (trw2),
                (trw3)
            ) AS Value(HighTrw)
        ) AS high_trw,
    i.knum AS Issued,
    isnull(i.DATE, '1980-01-01') AS Issued_Date,
    c.PBS#DISP AS MF_Disp,
    c.LN#DISP AS LN_Disp,
    c.PBS#DAYS#DELQ AS MF_Delq,
    c.PBS#FREQ AS MF_Freq,
    c.LN#CURR#BAL AS LN_Bal,
    c.LN#NPDD AS NPDD,
    p.PMTS_Made AS Pmts_Made,
    p.D30,
    p.D60,
    p.D90
FROM dbo.SPI S
LEFT JOIN dbo.combined C
    ON s.knum = c.k
LEFT JOIN dbo.payments P
    ON s.knum = p.knum
LEFT JOIN dbo.dvn D
    ON s.knum = d.knum
LEFT JOIN dbo.exclusion E
    ON s.knum = e.knum
LEFT JOIN dbo.issued I
    ON s.knum = i.knum
LEFT JOIN dbo.outfield O
    ON s.knum = o.knum
LEFT JOIN dbo.spi_tours ST
    ON s.customer_id = st.customer_id
LEFT JOIN dbo.magna M
    ON s.knum = m.knum
WHERE
    -- Part 1
    M.knum IS NULL
    AND D.Knum IS NULL
    AND O.knum IS NULL
    AND E.Knum IS NULL
    AND st.customer_id IS NULL
    -- Part 2
    AND (
        (
            c.pbs#freq = 'A'
            AND c.pbs#days#delq <= 716
            )
        OR (
            c.pbs#freq = 'E'
            AND c.pbs#days#delq <= 1446
            )
        OR (
            c.pbs#freq = 'O'
            AND c.pbs#days#delq <= 1081
            )
        )
    -- Part 3
    AND (
        i.DATE >= '2019-05-01'
        OR i.DATE IS NULL
        )
    -- Part 4
    AND (
        (
            p.d30 <= '6'
            OR p.d30 IS NULL
            )
        OR (
            p.d60 <= '1'
            OR p.d60 IS NULL
            )
        OR (
            p.d90 <= '0'
            OR p.d90 IS NULL
            )
        )
    AND (
        p.PMTS_Made >= '12'
        OR p.pmts_made IS NULL
        )
    AND CASE
        WHEN high_trw BETWEEN 625 AND 900
            AND c.LN#CURR#BAL BETWEEN '7500' AND '15000'
            THEN 1
        WHEN high_trw BETWEEN 600 AND 624
            AND c.LN#CURR#BAL BETWEEN '3000' AND '7499' -- Typo - was 499
            THEN 1
        ELSE 0
        END = 1

我相信这会满足你的需求。请注意,您从where子句中排除了high_trw value检查,因此我将它们重新添加到:

SELECT s.knum,
    m.knum AS M_knum,
    d.knum AS D_knum,
    o.knum AS O_knum,
    e.knum AS E_knum,
    s.customer_id,
    st.customer_id AS ST_Customer_id,
    s.fdd,
    s.STATUS,
    s.STATE,
    (
        SELECT max(HighTrw)
        FROM (
            VALUES (trw1),
                (trw2),
                (trw3)
            ) AS Value(HighTrw)
        ) AS high_trw,
    i.knum AS Issued,
    isnull(i.DATE, '1980-01-01') AS Issued_Date,
    c.PBS#DISP AS MF_Disp,
    c.LN#DISP AS LN_Disp,
    c.PBS#DAYS#DELQ AS MF_Delq,
    c.PBS#FREQ AS MF_Freq,
    c.LN#CURR#BAL AS LN_Bal,
    c.LN#NPDD AS NPDD,
    p.PMTS_Made AS Pmts_Made,
    p.D30,
    p.D60,
    p.D90
FROM dbo.SPI S
LEFT JOIN dbo.combined C
    ON s.knum = c.k
LEFT JOIN dbo.payments P
    ON s.knum = p.knum
LEFT JOIN dbo.dvn D
    ON s.knum = d.knum
LEFT JOIN dbo.exclusion E
    ON s.knum = e.knum
LEFT JOIN dbo.issued I
    ON s.knum = i.knum
LEFT JOIN dbo.outfield O
    ON s.knum = o.knum
LEFT JOIN dbo.spi_tours ST
    ON s.customer_id = st.customer_id
LEFT JOIN dbo.magna M
    ON s.knum = m.knum
WHERE
    -- Part 1
    M.knum IS NULL
    AND D.Knum IS NULL
    AND O.knum IS NULL
    AND E.Knum IS NULL
    AND st.customer_id IS NULL
    -- Part 2
    AND (
        (
            c.pbs#freq = 'A'
            AND c.pbs#days#delq <= 716
            )
        OR (
            c.pbs#freq = 'E'
            AND c.pbs#days#delq <= 1446
            )
        OR (
            c.pbs#freq = 'O'
            AND c.pbs#days#delq <= 1081
            )
        )
    -- Part 3
    AND (
        i.DATE >= '2019-05-01'
        OR i.DATE IS NULL
        )
    -- Part 4
    AND (
        (
            p.d30 <= '6'
            OR p.d30 IS NULL
            )
        OR (
            p.d60 <= '1'
            OR p.d60 IS NULL
            )
        OR (
            p.d90 <= '0'
            OR p.d90 IS NULL
            )
        )
    AND (
        p.PMTS_Made >= '12'
        OR p.pmts_made IS NULL
        )
    AND CASE
        WHEN high_trw BETWEEN 625 AND 900
            AND c.LN#CURR#BAL BETWEEN '7500' AND '15000'
            THEN 1
        WHEN high_trw BETWEEN 600 AND 624
            AND c.LN#CURR#BAL BETWEEN '3000' AND '7499' -- Typo - was 499
            THEN 1
        ELSE 0
        END = 1

啊,是的,谢谢你们两个回答似乎都很有效。从我所看到的问题来看,除了一些格式之外,我试图在每个where条件中输入所有空值,而不是使用isnull?我发现了一个问题,它与我没有解释的部分有关。当我添加你的格式部分时,它似乎否定了选择状态中的c.lncurrbal为null是的,谢谢你们两个答案似乎都很有效。从我所看到的问题来看,除了一些格式之外,我试图在每个where条件中输入所有空值,而不是使用isnull?我发现了一个问题,它与我没有解释的部分有关。当我添加你的格式化部分时,它似乎否定了select语句中的c.lncurrbal为null