2017-02-10 28 views
3

我想寫一些SQL來查詢銀行對賬單表,我想填充一列作爲'排除',如果任何5個銀行對賬單說明列包含'剩餘現金', 「CHQ在」或「ELECTR費」搜索多個包含多列的條件

我現在的嘗試是

select statement_no 
     ,bank_text_1 
     ,bank_text_2 
     ,bank_text_3 
     ,bank_text_4 
     ,bank_text_5 
     ,amount 
     ,case 
      when bank_text_1 like '%SURPLUS CASH%' 
       or bank_text_1 like '%CHQ IN AT%' 
       or bank_text_1 like '%ELECTR CHARGE%' 
       or bank_text_2 like '%SURPLUS CASH%' 
       or bank_text_2 like '%CHQ IN AT%' 
       or bank_text_2 like '%ELECTR CHARGE%' 
       or bank_text_3 like '%SURPLUS CASH%' 
       or bank_text_3 like '%CHQ IN AT%' 
       or bank_text_3 like '%ELECTR CHARGE%' 
       or bank_text_4 like '%SURPLUS CASH%' 
       or bank_text_4 like '%CHQ IN AT%' 
       or bank_text_4 like '%ELECTR CHARGE%' 
       or bank_text_5 like '%SURPLUS CASH%' 
       or bank_text_5 like '%CHQ IN AT%' 
       or bank_text_5 like '%ELECTR CHARGE%' 
       then 'Exclude' 
      else '' 
     end as checker; 

這是非常亂,而且似乎不是很有效率。有沒有人有更好的方法建議?

非常感謝

例結果數據:

Statement_no | bank_text_1 | bank_text_2   | bank_text_3 | bank_text_4 | bank_text_5 | amount | checker 
0001   | SURPLUS CASH|      |    |    |    |125.00 |Exclude 
0002   | M THOMAS |TRAINING FEE   |CHQ IN AT 100217|    |    |470.00 |Exclude 
0003   |SWALEC  |Training Centre One |Abergaveny  |    |Electr Charges|700.00 |Exlcude 
0004   |M Thomas  |Training Centre Hire |    |    |    |850.00 | 
+0

如果您使用某種數據訪問方式,如JDBC(Java)或ADO.NET(.NET),則可以使用參數。使用參數使您的查詢不再混亂。我更喜歡你已經擁有的方式,因爲它很容易維護。 – Loc

回答

2

一個選擇是CROSS APPLY

Select statement_no 
    , bank_text_1 
    , bank_text_2 
    , bank_text_3 
    , bank_text_4 
    , bank_text_5 
    , amount 
    , B.Checker 
From YourTable A 
Cross Apply (Select Checker = case when count(*)>0 then 'Exclude' else '' end 
       From (values (A.bank_text_1) 
        ,(A.bank_text_2) 
        ,(A.bank_text_3) 
        ,(A.bank_text_4) 
        ,(A.bank_text_5)) C1 (Value) 
       Where charindex('SURPLUS CASH',Value) 
        +charindex('CHQ IN AT',Value) 
        +charindex('ELECTR CHARGE',Value) 
        >0 
      ) B 

返回

enter image description here

+0

省長。非常感謝,正是我需要的。之前從未聽說過Cross申請...週末寫作和提前谷歌搜尋。乾杯約翰。 – BlueFrog

+0

@BlueFrog快樂它幫助。 CROSS APPLY是一個很棒的功能。把它看作子程序 –

0

這看起來有點整潔,應該同樣,雖然執行:

SELECT statement_no, 
     bank_text_1, bank_text_2, bank_text_3, bank_text_4, bank_text_5, 
     amount, 
     IIF(x.IsChecked = 1, 'Exclude', '') 
FROM mytable 
CROSS APPLY (
    SELECT SUM(CASE 
       WHEN (t.v LIKE '%SURPLUS CASH%') OR 
         (t.v LIKE '%CHQ IN AT%') OR 
         (t.v LIKE '%ELECTR CHARGE%') 
        THEN 1 
       ELSE 0 
       END) AS IsChecked 
    FROM 
    (  
     VALUES (bank_text_1), (bank_text_2), (bank_text_3), (bank_text_4), (bank_text_5) 
    ) AS t(v) 
) AS x 
+0

這會爲每個原始行返回5行。 http://rextester.com/BMYSM47521 – SqlZim

+0

@SqlZim道歉,我現在糾正它! –

0

你應該嘗試:

select statement_no 
     ,bank_text_1 
     ,bank_text_2 
     ,bank_text_3 
     ,bank_text_4 
     ,bank_text_5 
     ,amount 
     ,case 
      when q.item is not null 
       then 'Exclude' 
      else '' 
     end as checker 
from queries 
left join 
(
     select '%CHQ IN AT%' item union 
     select '%ELECTR CHARGE%' item union  
     select '%SURPLUS CASH%' item 
) q on bank_text_1 like item or 
     bank_text_2 like item or 
     bank_text_3 like item or 
     bank_text_4 like item or 
     bank_text_5 like item 

我不知道的性能,但在我看來聯接是輕於交叉應用。如果你可以分享基準,我會感興趣。

1
select * 
, checker = case 
    when charindex('SURPLUS CASH',concat(bank_text_1, bank_text_2, bank_text_3, bank_text_4, bank_text_5))>0 
     or charindex('CHQ IN AT',concat(bank_text_1, bank_text_2, bank_text_3, bank_text_4, bank_text_5))>0 
     or charindex('ELECTR CHARGE',concat(bank_text_1, bank_text_2, bank_text_3, bank_text_4, bank_text_5))>0 
     then 'Exclude' 
    else '' 
    end 
from t 

結果:http://rextester.com/VBOC27547

+--------------+---------------+-----------------------+------------------+-------------+----------------+--------+---------+ 
| statement_no | bank_text_1 |  bank_text_2  | bank_text_3 | bank_text_4 | bank_text_5 | amount | checker | 
+--------------+---------------+-----------------------+------------------+-------------+----------------+--------+---------+ 
|   0001 | SURPLUS CASH |      |     |    |    | 125,00 | Exclude | 
|   0002 | M THOMAS  | TRAINING FEE   | CHQ IN AT 100217 |    |    | 470,00 | Exclude | 
|   0003 | SWALEC  | Training Centre One | Abergaveny  |    | Electr Charges | 700,00 | Exclude | 
|   0004 | M Thomas  | Training Centre Hire |     |    |    | 850,00 |   | 
+--------------+---------------+-----------------------+------------------+-------------+----------------+--------+---------+ 

我測試的這個性能相比約翰·卡佩萊蒂的回答超過100多萬行,我不認爲他們是可比的。

我個人的偏好是約翰的回答,使用cross apply()

在下面的集合中,每個集合中的第一個查詢使用charindex(...,concat(..),第二個查詢是約翰的cross apply()版本。

雖然這個實例的硬件規格相當薄弱,所以你的里程會有所不同。

----------------------- 

(1000000 row(s) affected) 
Table 't'. Scan count 1, logical reads 8153, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 3010 ms, elapsed time = 8750 ms. 

(1000000 row(s) affected) 
Table 't'. Scan count 1, logical reads 8153, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 5585 ms, elapsed time = 8725 ms. 

----------------------- 

(1000000 row(s) affected) 
Table 't'. Scan count 1, logical reads 8153, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 3307 ms, elapsed time = 8685 ms. 

(1000000 row(s) affected) 
Table 't'. Scan count 1, logical reads 8153, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 5663 ms, elapsed time = 8913 ms. 

----------------------- 

(1000000 row(s) affected) 
Table 't'. Scan count 1, logical reads 8153, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 3073 ms, elapsed time = 8414 ms. 

(1000000 row(s) affected) 
Table 't'. Scan count 1, logical reads 8153, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 5647 ms, elapsed time = 9049 ms. 

------------------- 

(1000000 row(s) affected) 
Table 't'. Scan count 1, logical reads 8153, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 3011 ms, elapsed time = 8706 ms. 

(1000000 row(s) affected) 
Table 't'. Scan count 1, logical reads 8153, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

SQL Server Execution Times: 
    CPU time = 5491 ms, elapsed time = 8704 ms. 

----------------------- 
+0

走多走的路+1 –

+0

@JohnCappelletti謝謝 – SqlZim