2016-04-27 86 views
2

我想將五列(x1-x5)與五列(y1-y5)進行比較,以確定它們同意的程度(以任意順序)。將五列與SQL中的其他五列進行比較

對於匹配(在五列y1-y5中的任何一列中)的值的數量(在x1-x5中),得分範圍從0到5。

我可以把它寫成CASE WHEN語句的冗長系列,但是有沒有更高效的方法來實現這一點?

這些值都是字符串。全文搜索在服務器上不可用。

下面的代碼舉例說明了一個例子,其中n_found是我試圖創建的。

DROP TABLE mytable; 
CREATE TABLE mytable(
    id  INTEGER NOT NULL PRIMARY KEY 
    ,x1  VARCHAR(1) NOT NULL 
    ,x2  VARCHAR(1) NOT NULL 
    ,x3  VARCHAR(1) NOT NULL 
    ,x4  VARCHAR(1) NOT NULL 
    ,x5  VARCHAR(1) NOT NULL 
    ,y1  VARCHAR(1) NOT NULL 
    ,y2  VARCHAR(1) NOT NULL 
    ,y3  VARCHAR(1) NOT NULL 
    ,y4  VARCHAR(1) NOT NULL 
    ,y5  VARCHAR(1) NOT NULL 
    ,n_found INTEGER NOT NULL 
); 
INSERT INTO mytable(id,x1,x2,x3,x4,x5,y1,y2,y3,y4,y5,n_found) 
VALUES (1,'a','b','c','d','e','r','a','t','y','z',1); 
INSERT INTO mytable(id,x1,x2,x3,x4,x5,y1,y2,y3,y4,y5,n_found) 
VALUES (2,'e','a','b','d','c','m','o','a','b','z',2); 
INSERT INTO mytable(id,x1,x2,x3,x4,x5,y1,y2,y3,y4,y5,n_found) 
VALUES (3,'a','b','c','d','e','f','g','h','i','j',0); 
INSERT INTO mytable(id,x1,x2,x3,x4,x5,y1,y2,y3,y4,y5,n_found) 
VALUES (4,'a','b','c','d','e','b','e','a','c','d',5); 
INSERT INTO mytable(id,x1,x2,x3,x4,x5,y1,y2,y3,y4,y5,n_found) 
VALUES (5,'a','b','c','e','d','d','b','x','y','z',2); 

回答

2

你可以使用CROSS APPLY和表值構造:

SELECT * 
FROM mytable 
CROSS APPLY (SELECT COUNT(*) 
      FROM (VALUES (x1),(x2),(x3),(x4),(x5)) AS t1(v) 
      WHERE v IN (SELECT v 
         FROM (VALUES (y1),(y2),(y3),(y4),(y5)) AS t2(v)) 
      ) AS s(found); 

LiveDemo

輸出:

╔═════════════════════════════════════════════════╗ 
║ id x1 x2 x3 x4 x5 y1 y2 y3 y4 y5 n_found found ║ 
╠═════════════════════════════════════════════════╣ 
║ 1 a b c d e r a t y z 1  1  ║ 
║ 2 e a b d c m o a b z 2  2  ║ 
║ 3 a b c d e f g h i j 0  0  ║ 
║ 4 a b c d e b e a c d 5  5  ║ 
║ 5 a b c e d d b x y z 2  2  ║ 
╚═════════════════════════════════════════════════╝ 

注:

如果你想處理NULLs你可以使用COALESCE與價值交換NULL,你就一定不存在:

COALESCE(x1,'^') 

LiveDemo2

編輯:

這似乎評估NULL爲同意。你可以修改它,使NULL與NULL相比不匹配嗎?

正如我之前所說,它已經在以這種方式工作。

LiveDemo3

╔════╦════╦════╦════╦════╦══════╦════╦════╦════╦════╦══════╦═════════╦═══════╗ 
║ id ║ x1 ║ x2 ║ x3 ║ x4 ║ x5 ║ y1 ║ y2 ║ y3 ║ y4 ║ y5 ║ n_found ║ found ║ 
╠════╬════╬════╬════╬════╬══════╬════╬════╬════╬════╬══════╬═════════╬═══════╣ 
║ 6 ║ a ║ a ║ c ║ e ║ NULL ║ o ║ y ║ x ║ y ║ NULL ║  0 ║  0 ║ 
╚════╩════╩════╩════╩════╩══════╩════╩════╩════╩════╩══════╩═════════╩═══════╝ 

編輯2:

要處理NULL你也可以使用INTERSECT (ALL)相當於:

SELECT * 
FROM mytable 
CROSS APPLY (SELECT COUNT(*) 
      FROM (SELECT v, 
         ROW_NUMBER() OVER(PARTITION BY v ORDER BY (SELECT 1)) AS c 
        FROM (VALUES (x1),(x2),(x3),(x4),(x5)) AS t1(v) 
        INTERSECT 
        SELECT v, 
         ROW_NUMBER() OVER(PARTITION BY v ORDER BY (SELECT 1)) 
        FROM (VALUES (y1),(y2),(y3),(y4),(y5)) AS t2(v) 
       ) AS s2 
      ) AS s(found) 

LiveDemo4

+0

這似乎評估NULL作爲同意。我看到你上面提到了COALESCE,你能修改代碼來說明如何在這個例子中使用COALESCE嗎?我以前沒有用過它。 – user2964644

+0

@ user2964644請檢查更新後的答案。 – lad2025

0

不漂亮,但可能表現得比跨更好地應用選項。

SELECT *, 
     CASE WHEN x1 IN (y1, y2, y3, y4, y5) THEN 1 ELSE 0 END 
     + CASE WHEN x2 IN (y1, y2, y3, y4, y5) THEN 1 ELSE 0 END 
     + CASE WHEN x3 IN (y1, y2, y3, y4, y5) THEN 1 ELSE 0 END 
     + CASE WHEN x4 IN (y1, y2, y3, y4, y5) THEN 1 ELSE 0 END 
     + CASE WHEN x5 IN (y1, y2, y3, y4, y5) THEN 1 ELSE 0 END 
FROM myTable 

Demo

+0

它不會處理'NULL' :) – lad2025

+0

@ lad2025它不計算空值,我認爲這是一個要求 – JamieD77

相關問題