SQL只查找某些日期之前的记录

时间:2018-01-18 10:27:10

标签: sql sql-server tsql

我有上面的2个表及其各自的列。

HEADER
    PO_Number (char)
    CUSTNMBR (char)
    Expiry_Date (datetime)
    PO_Status (tinyint, 0 = Open, 1 = Closed)
    STATUSDATE (datetime)

BATCH
    PORDNMBR (char)
    CUSTNMBR (char)
    BTCHID (char)
    DATE1 (datetime)

在HEADER表中,主键是(PO_Number,CUSTNMBR)。 在BATCH表中,BTCHID是主键。 DATE1列是输入相应批次的日期。 此外,对于HEADER表中的每个(PO_Number,CUSTNMBR)组合,可能在不同日期输入多个BTCHID。 我的截止日期为2016-07-12,截止日期前有批次,截止日期后有批次。

我需要识别那些在截止日期之后没有输入任何批次的(PO_Number,CUSTNMBR)组合,其中Expiry_Date形式HEADER是<截止日期。

我最初编写了以下查询,但结果是带来了截止日期后也有批次的记录。我已经通过键入PORDNMBR验证了从BATCH查询中使用SELECT *,结果我可以在截止日期之前和截止日期之后看到批次。是否有任何方法可以识别那些在截止日期之后没有输入任何批次的那些并且Expiry_Date形式HEADER是<截止日期?

SELECT BATCH.PORDNMBR, BATCH.CUSTNMBR, BATCH.BTCHID, BATCH.DATE1, 
HEADER.PO_Number, HEADER.CUSTNMBR, HEADER.Expiry_Date, HEADER.PO_Status, HEADER.STATUSDATE
FROM           BATCH
INNER JOIN
               HEADER
ON 
BATCH.CUSTNMBR = HEADER.CUSTNMBR 
AND 
BATCH.PORDNMBR = HEADER.PO_Number
WHERE BATCH.Expiry_Date < '2016-07-12 00:00:00'
AND BATCH.DATE1 < '2016-07-12 00:00:00'

3 个答案:

答案 0 :(得分:0)

加入一个标识有效批次的子查询:

SELECT
    b1.PORDNMBR,
    b1.CUSTNMBR,
    b1.BTCHID,
    b1.DATE1, 
    h.PO_Number,
    h.CUSTNMBR,
    h.Expiry_Date,
    h.PO_Status,
    h.STATUSDATE
FROM BATCH b1
INNER JOIN
(
    SELECT PORDNMBR, CUSTNMBR
    FROM BATCH
    GROUP BY PORDNMBR, CUSTNMBR
    HAVING SUM(CASE WHEN Expiry_Date >= '2016-07-12 00:00:00' THEN 1 ELSE 0 END) = 0
) b2
    ON b1.PORDNMBR = b2.PORDNMBR AND
       b1.CUSTNMBR = b2.CUSTNMBR
INNER JOIN HEADER h
    ON b1.CUSTNMBR = h.CUSTNMBR AND 
       b1.PORDNMBR = h.PO_Number
WHERE
    b1.DATE1 < '2016-07-12 00:00:00';

您当前逻辑的问题在于您正在WHERE子句中对每条记录应用到期日期逻辑。但是你真的想把这个逻辑应用于记录组。

答案 1 :(得分:0)

嗯。我想你只是想要标题信息,所以not exists会浮现在脑海中:

select h.*
from header h
where not exists (select 1
                  from batch b
                  where b.pordnmbr = h.prodnmbr and
                        b.custnmbr = h.custnmbr and
                        b.Expiry_Date < '2016-07-12' and
                        b.date1 > '2016-07-12'
                 );

日期算术与您的查询略有不同,与您描述的逻辑相匹配。

答案 2 :(得分:0)

您的查询只会删除批次中的行 - 而不是整个批次

我认为这会起作用

declare @Expiry_Date datetime = '2016-07-12 00:00:00';

SELECT B.PORDNMBR, B.CUSTNMBR, B.BTCHID, B.DATE1, 
       H.PO_Number, H.CUSTNMBR, H.Expiry_Date, H.PO_Status, H.STATUSDATE
FROM   ( select * 
         from header 
         where Expiry_Date < @Expiry_Date
       ) H
JOIN BATCH B
  ON B.CUSTNMBR = H.CUSTNMBR 
 AND B.PORDNMBR = H.PO_Number
 AND NOT EXISTS ( SELECT 1 from batch 
                   WHERE BATCH.CUSTNMBR = H.CUSTNMBR 
                     AND BATCH.PORDNMBR = H.PO_Number 
                     AND BATCH.DATE1 >= @Expiry_Date 
                )
ORDER BY B.CUSTNMBR, B.PORDNMBR, B.BTCHID