比较SQL中的五列到五列

时间:2016-04-27 12:43:56

标签: sql sql-server-2008 tsql search case

我想比较五列(x1-x5)和另外五列(y1-y5),以确定它们达成一致的程度(以任何顺序)。

对于匹配的值(在x1-x5中)(在五列y1-y5中的任何一列中),奖励从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 个答案:

答案 0 :(得分: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

答案 1 :(得分: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