2016-04-27 96 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

相关问题