SQL Server 2014 - 如何排除没有特定值的记录?
SQL Server 2014 - How to Exclude records that don't have a certain value?
我有一个基于交易日期的派生温度 table,如下所述:
-----------------------------------------------------------------------------------
|Account_No| Customer_Name | Invoice_No | Amount | Reason_Comment | Trans_Code |
-----------------------------------------------------------------------------------
|12345678 | John Doe | A23782998 | 326.28 | Payment | 2 |
-----------------------------------------------------------------------------------
|12345678 | John Doe | A23782998 | 173.72 | Adjustment | 3 |
-----------------------------------------------------------------------------------
|12345678 | John Doe | A23782998 | 0.00 | Paid In Full | X |
-----------------------------------------------------------------------------------
|23456789 | Bob Marley | B58787934 | 500.00 | Payment | 2 |
-----------------------------------------------------------------------------------
|23456789 | Bob Marley | B58787934 | 0.00 | Paid In Full | X |
-----------------------------------------------------------------------------------
|89034537 | Eric Clapton | C78236428 | 0.00 | Paid In Full | X |
-----------------------------------------------------------------------------------
如您所见,Bob Markey 进行了付款,他的帐户显示为 'Paid In Full'。
埃里克克莱普顿很顺利。他较早付款,因此已经显示为 'Paid In Full'
John Doe 需要 'Adjustment' 形式的一点帮助,以便我们可以将他的账户余额归零,因此 'Paid In Full'
付款交易的 Trans_Code 为 2,调整为 3 并全额支付为 X。
我想排除在 TransCode 中只有 'Paid In Full' 原因或 X 的交易。
我试过:
SELECT *
FROM #temp_table
WHERE Account_No NOT IN
(SELECT Account_No FROM #temp_table
WHERE Reason_Comment = 'Paid In FUll'
AND Reason_Comment <> 'PAYMENT'
AND Reason_Comment <> 'ADJUSTMENT')
也许,我应该用一个NOT EXISTS
编辑:
这是我正在使用的 table。因为我指定了一个日期范围,一些账户只有一行,即 'Paid In Full' 行,因为调整或付款发生在指定的日期范围之前。例如,下面 table 中的最后一行 (Johnson Doe)。我想排除最后一行。
----------------------------------------------------------------------------------------------------------
|Account_No| Customer_Name | Invoice_No | Amount | Trans_No |Reason_Comment | Trans_Date | Trans_Code|
----------------------------------------------------------------------------------------------------------
|12345678 | John Doe | A23782998 | 326.28 |1234567 |Payment | 2018-04-01 | 2|
----------------------------------------------------------------------------------------------------------
|12345678 | John Doe | A23782998 | 687.58 | |Amount Due | | 4|
----------------------------------------------------------------------------------------------------------
|23456789 | Jane Doe | B12378299 | 123.56 |2345678 |Payment | 2018-04-02 | 2|
----------------------------------------------------------------------------------------------------------
|23456789 | Jane Doe | B12378299 | 336.44 |3456789 |Adjustment | 2018-04-03 | 3|
----------------------------------------------------------------------------------------------------------
|23456789 | Jane Doe | B12378299 | | |Paid In Full | | X|
----------------------------------------------------------------------------------------------------------
|34567890 | Jonas Doe | C34567998 | 500.55 |4567891 |Payment | 2018-04-06 | 2|
----------------------------------------------------------------------------------------------------------
|34567890 | Jonas Doe | C34567998 | | |Paid In Full | | X|
----------------------------------------------------------------------------------------------------------
|45678912 | Johnson Doe | D45678756 | | |Paid In Full | | X|
----------------------------------------------------------------------------------------------------------
您可以使用:
SELECT *
FROM tab t
WHERE NOT EXISTS (SELECT 1
FROM tab t2
WHERE t.Account_no = t2.Account_no
AND t.Invoice_no = t2.Invoice_no
AND (Reason_Comment IN ('Paid In FUll')
OR TransCode = 'X')
);
--你可以用不同的方式写查询
SELECT *
FROM #temptable
WHERE Reason_Comment != 'Paid In FUll' AND trans_code != 'X'
SELECT *
FROM #temptable
EXCEPT
SELECT *
FROM #temptable
WHERE Reason_Comment = 'Paid In FUll'
OR trans_code = 'X'
正如我在评论中所述,您的 post 并不是很清楚您到底需要排除什么,但是根据您提供的示例和查询,我得出的结论是您需要排除没有任何调整或分期付款计划的客户(像您示例中的 Eric Clapton 这样的人),因为您为什么需要跟踪已经全额支付(预付或早于到期)的付款,您不认为跟进有分期付款或调整的人以确保您获得全额付款?
这就是我理解你的问题的方式,这对我来说(也许)是有意义的。
如果这就是您要找的,那么您可以这样做:
已更新(使用新提供的示例)
SELECT
Account_No,
Customer_Name,
Invoice_No,
Amount,
Trans_No,
Reason_Comment,
Trans_Date,
Trans_Code
FROM(
SELECT
Account_No,
Customer_Name,
Invoice_No,
Amount,
Trans_No,
Reason_Comment,
Trans_Code,
CASE
WHEN
COUNT(Account_No) OVER(PARTITION BY Account_No) = 1 AND Trans_Code = 'X'
THEN NULL
ELSE
COUNT(Account_No) OVER(PARTITION BY Account_No)
END AS NumberOfPayments,
Trans_Date
FROM Trans
) D
WHERE
NumberOfPayments IS NOT NULL
AND (
CAST(Trans_Date AS DATE) >= '2018-04-01'
AND CAST(Trans_Date AS DATE) <= '2018-04-06'
OR Trans_Date IS NULL
)
这会 return :
| Account_No | Customer_Name | Invoice_No | Amount | Trans_No | Reason_Comment | Trans_Date | Trans_Code |
|------------|---------------|------------|--------|----------|----------------|----------------------|------------|
| 12345678 | John Doe | A23782998 | 326.28 | 1234567 | Payment | 2018-04-01T00:00:00Z | 2 |
| 12345678 | John Doe | A23782998 | 687.58 | (null) | Amount Due | (null) | 4 |
| 23456789 | Jane Doe | B12378299 | 123.56 | 2345678 | Payment | 2018-04-02T00:00:00Z | 2 |
| 23456789 | Jane Doe | B12378299 | 336.44 | 3456789 | Adjustment | 2018-04-03T00:00:00Z | 3 |
| 23456789 | Jane Doe | B12378299 | (null) | (null) | Paid In Full | (null) | X |
| 34567890 | Jonas Doe | C34567998 | 500.55 | 4567891 | Payment | 2018-04-06T00:00:00Z | 2 |
| 34567890 | Jonas Doe | C34567998 | (null) | (null) | Paid In Full | (null) | X |
NumberOfPayments 将根据发票编号计算每个帐号的付款。
您可以根据需要更改 CASE
规则,您还可以添加对分期付款有用的付款订单(付款 1、付款 2、付款 3 等)。您需要做的就是添加这一行:
ROW_NUMBER() OVER(PARTITION BY Invoice_No ORDER BY Trans_Code) AS PaymnetNumber
这是一个Fiddle Demo
我有一个基于交易日期的派生温度 table,如下所述:
-----------------------------------------------------------------------------------
|Account_No| Customer_Name | Invoice_No | Amount | Reason_Comment | Trans_Code |
-----------------------------------------------------------------------------------
|12345678 | John Doe | A23782998 | 326.28 | Payment | 2 |
-----------------------------------------------------------------------------------
|12345678 | John Doe | A23782998 | 173.72 | Adjustment | 3 |
-----------------------------------------------------------------------------------
|12345678 | John Doe | A23782998 | 0.00 | Paid In Full | X |
-----------------------------------------------------------------------------------
|23456789 | Bob Marley | B58787934 | 500.00 | Payment | 2 |
-----------------------------------------------------------------------------------
|23456789 | Bob Marley | B58787934 | 0.00 | Paid In Full | X |
-----------------------------------------------------------------------------------
|89034537 | Eric Clapton | C78236428 | 0.00 | Paid In Full | X |
-----------------------------------------------------------------------------------
如您所见,Bob Markey 进行了付款,他的帐户显示为 'Paid In Full'。
埃里克克莱普顿很顺利。他较早付款,因此已经显示为 'Paid In Full'
John Doe 需要 'Adjustment' 形式的一点帮助,以便我们可以将他的账户余额归零,因此 'Paid In Full'
付款交易的 Trans_Code 为 2,调整为 3 并全额支付为 X。
我想排除在 TransCode 中只有 'Paid In Full' 原因或 X 的交易。
我试过:
SELECT *
FROM #temp_table
WHERE Account_No NOT IN
(SELECT Account_No FROM #temp_table
WHERE Reason_Comment = 'Paid In FUll'
AND Reason_Comment <> 'PAYMENT'
AND Reason_Comment <> 'ADJUSTMENT')
也许,我应该用一个NOT EXISTS
编辑:
这是我正在使用的 table。因为我指定了一个日期范围,一些账户只有一行,即 'Paid In Full' 行,因为调整或付款发生在指定的日期范围之前。例如,下面 table 中的最后一行 (Johnson Doe)。我想排除最后一行。
----------------------------------------------------------------------------------------------------------
|Account_No| Customer_Name | Invoice_No | Amount | Trans_No |Reason_Comment | Trans_Date | Trans_Code|
----------------------------------------------------------------------------------------------------------
|12345678 | John Doe | A23782998 | 326.28 |1234567 |Payment | 2018-04-01 | 2|
----------------------------------------------------------------------------------------------------------
|12345678 | John Doe | A23782998 | 687.58 | |Amount Due | | 4|
----------------------------------------------------------------------------------------------------------
|23456789 | Jane Doe | B12378299 | 123.56 |2345678 |Payment | 2018-04-02 | 2|
----------------------------------------------------------------------------------------------------------
|23456789 | Jane Doe | B12378299 | 336.44 |3456789 |Adjustment | 2018-04-03 | 3|
----------------------------------------------------------------------------------------------------------
|23456789 | Jane Doe | B12378299 | | |Paid In Full | | X|
----------------------------------------------------------------------------------------------------------
|34567890 | Jonas Doe | C34567998 | 500.55 |4567891 |Payment | 2018-04-06 | 2|
----------------------------------------------------------------------------------------------------------
|34567890 | Jonas Doe | C34567998 | | |Paid In Full | | X|
----------------------------------------------------------------------------------------------------------
|45678912 | Johnson Doe | D45678756 | | |Paid In Full | | X|
----------------------------------------------------------------------------------------------------------
您可以使用:
SELECT *
FROM tab t
WHERE NOT EXISTS (SELECT 1
FROM tab t2
WHERE t.Account_no = t2.Account_no
AND t.Invoice_no = t2.Invoice_no
AND (Reason_Comment IN ('Paid In FUll')
OR TransCode = 'X')
);
--你可以用不同的方式写查询
SELECT *
FROM #temptable
WHERE Reason_Comment != 'Paid In FUll' AND trans_code != 'X'
SELECT *
FROM #temptable
EXCEPT
SELECT *
FROM #temptable
WHERE Reason_Comment = 'Paid In FUll'
OR trans_code = 'X'
正如我在评论中所述,您的 post 并不是很清楚您到底需要排除什么,但是根据您提供的示例和查询,我得出的结论是您需要排除没有任何调整或分期付款计划的客户(像您示例中的 Eric Clapton 这样的人),因为您为什么需要跟踪已经全额支付(预付或早于到期)的付款,您不认为跟进有分期付款或调整的人以确保您获得全额付款? 这就是我理解你的问题的方式,这对我来说(也许)是有意义的。
如果这就是您要找的,那么您可以这样做:
已更新(使用新提供的示例)
SELECT
Account_No,
Customer_Name,
Invoice_No,
Amount,
Trans_No,
Reason_Comment,
Trans_Date,
Trans_Code
FROM(
SELECT
Account_No,
Customer_Name,
Invoice_No,
Amount,
Trans_No,
Reason_Comment,
Trans_Code,
CASE
WHEN
COUNT(Account_No) OVER(PARTITION BY Account_No) = 1 AND Trans_Code = 'X'
THEN NULL
ELSE
COUNT(Account_No) OVER(PARTITION BY Account_No)
END AS NumberOfPayments,
Trans_Date
FROM Trans
) D
WHERE
NumberOfPayments IS NOT NULL
AND (
CAST(Trans_Date AS DATE) >= '2018-04-01'
AND CAST(Trans_Date AS DATE) <= '2018-04-06'
OR Trans_Date IS NULL
)
这会 return :
| Account_No | Customer_Name | Invoice_No | Amount | Trans_No | Reason_Comment | Trans_Date | Trans_Code |
|------------|---------------|------------|--------|----------|----------------|----------------------|------------|
| 12345678 | John Doe | A23782998 | 326.28 | 1234567 | Payment | 2018-04-01T00:00:00Z | 2 |
| 12345678 | John Doe | A23782998 | 687.58 | (null) | Amount Due | (null) | 4 |
| 23456789 | Jane Doe | B12378299 | 123.56 | 2345678 | Payment | 2018-04-02T00:00:00Z | 2 |
| 23456789 | Jane Doe | B12378299 | 336.44 | 3456789 | Adjustment | 2018-04-03T00:00:00Z | 3 |
| 23456789 | Jane Doe | B12378299 | (null) | (null) | Paid In Full | (null) | X |
| 34567890 | Jonas Doe | C34567998 | 500.55 | 4567891 | Payment | 2018-04-06T00:00:00Z | 2 |
| 34567890 | Jonas Doe | C34567998 | (null) | (null) | Paid In Full | (null) | X |
NumberOfPayments 将根据发票编号计算每个帐号的付款。
您可以根据需要更改 CASE
规则,您还可以添加对分期付款有用的付款订单(付款 1、付款 2、付款 3 等)。您需要做的就是添加这一行:
ROW_NUMBER() OVER(PARTITION BY Invoice_No ORDER BY Trans_Code) AS PaymnetNumber
这是一个Fiddle Demo