T-SQL:如何在没有游标的情况下查找匹配的记录

时间:2015-03-26 08:02:33

标签: sql-server performance tsql

我有两个表:ItemCriteria和Item

ItemCriteria具有以下字段

ID
Criteria1
Criteria2
Criteria3
Criteria4
Criteria5

项目具有相同的字段,不包括ID字段

我需要在Item表中找到包含一个或多个匹配条件字段(不包括NULLS)的所有项目,并返回匹配数。

因此,例如,如果我在ItemCriteria中有如下记录:

+----+-----------+-----------+-----------+-----------+-----------+
| ID | Criteria1 | Criteria2 | Criteria3 | Criteria4 | Criteria5 |
+----+-----------+-----------+-----------+-----------+-----------+
|  1 | NULL      | AAB       | AAC       | NULL      | NULL      |
|  2 | AAB       | NULL      | NULL      | NULL      | NULL      |
|  3 | NULL      | AAC       | NULL      | NULL      | NULL      |
|  4 | AAA       | NULL      | AAC       | NULL      | NULL      |
|  5 | BBB       | AAB       | NULL      | NULL      | NULL      |
+----+-----------+-----------+-----------+-----------+-----------+

我在Item

中有以下行
+-----------+-----------+-----------+-----------+-----------+
| Criteria1 | Criteria2 | Criteria3 | Criteria4 | Criteria5 |
+-----------+-----------+-----------+-----------+-----------+
| AAA       | AAB       | AAC       | NULL      | NULL      |
| AAB       | AAC       | NULL      | NULL      | NULL      |
+-----------+-----------+-----------+-----------+-----------+

我希望结果是:

+-----------+-----------+-----------+-----------+-----------+------------------+----------------+
| Criteria1 | Criteria2 | Criteria3 | Criteria4 | Criteria5 | MatchingCriteria | ItemCriteriaID |
+-----------+-----------+-----------+-----------+-----------+------------------+----------------+
| AAA       | AAB       | AAC       | NULL      | NULL      |                2 |              1 |
| AAB       | AAC       | NULL      | NULL      | NULL      |                1 |              2 |
| AAB       | AAC       | NULL      | NULL      | NULL      |                1 |              3 |
| AAA       | AAB       | AAC       | NULL      | NULL      |                2 |              4 |
| AAA       | AAB       | AAC       | NULL      | NULL      |                1 |              5 |
+-----------+-----------+-----------+-----------+-----------+------------------+----------------+

目前我有一个存储过程,在ItemCriteria上打开游标并逐步执行条目,然后为每个条目 创建一个执行的动态SQL语句。查询结果将插入到临时表中。一旦完成, 处理临时表中的值,并将结果返回给调用者。

当涉及大量记录时,这非常慢。有更好/更快的方法吗?

2 个答案:

答案 0 :(得分:0)

如果我已正确理解要求,那么它非常简单。您可以在连接中使用多个ORed条件。正如你所提到的,可能有多个匹配我在CROSS APPLY中使用SELECT TOP 1来确保我们只得到1个匹配 - 如果这不能给你所需的匹配,那么你可以在子选择中添加一个ORDER BY

declare @ItemCriteria table (id int, criteria1 char(3), criteria2 char(3), criteria3 char(3), criteria4 char(3), criteria5 char(3))
declare @Item table (criteria1 char(3), criteria2 char(3), criteria3 char(3), criteria4 char(3), criteria5 char(3))

insert @ItemCriteria values 
    (1 , NULL, 'AAB', 'AAC', NULL, NULL),
    (2 ,'AAB', NULL, NULL, NULL, NULL),
    (3 , NULL, 'AAC', NULL, NULL, NULL),
    (4 ,'AAA', NULL, 'AAC', NULL, NULL),
    (5 ,'BBB', 'AAB', NULL, NULL, NULL)

insert @item values 
    ('AAA', 'AAB', 'AAC', NULL, NULL),
    ('AAB', 'AAC', NULL, NULL, NULL)

select
    coalesce(i.criteria1, ic.criteria1) as Criteria1,
    coalesce(i.criteria2, ic.criteria2) as Criteria2,
    coalesce(i.criteria3, ic.criteria3) as Criteria3,
    coalesce(i.criteria4, ic.criteria4) as Criteria4,
    coalesce(i.criteria5, ic.criteria5) as Criteria5,
    case when i.criteria1 = ic.criteria1 then 1 else 0 end +
        case when i.criteria2 = ic.criteria2 then 1 else 0 end +
        case when i.criteria3 = ic.criteria3 then 1 else 0 end +
        case when i.criteria4 = ic.criteria4 then 1 else 0 end +
        case when i.criteria5 = ic.criteria5 then 1  else 0 end as MatchingCriteria,
    ic.id as ItemCriteriaID
from
    @ItemCriteria ic
        left join @Item i on i.criteria1 = ic.criteria1 
                          or i.criteria2 = ic.criteria2 
                          or i.criteria3 = ic.criteria3 
                          or i.criteria4 = ic.criteria4 
                          or i.criteria5 = ic.criteria5

答案 1 :(得分:0)

在这里尝试一下:

IF OBJECT_ID('tempdb..#ItemCriteria') IS NOT NULL
    DROP TABLE #ItemCriteria
IF OBJECT_ID('tempdb..#Item') IS NOT NULL
    DROP TABLE #Item

CREATE TABLE #ItemCriteria
(
    ID INT,
    Criteria1 VARCHAR(5),
    Criteria2 VARCHAR(5),
    Criteria3 VARCHAR(5),
    Criteria4 VARCHAR(5),
    Criteria5 VARCHAR(5),
)

INSERT INTO #ItemCriteria
VALUES  (1,NULL,'AAB','AAC',NULL,NULL),
        (2,'AAB',NULL,NULL,NULL,NULL),
        (3,NULL,'AAC',NULL,NULL,NULL),
        (4,'AAA',NULL,'AAC',NULL,NULL),
        (5,'BBB','AAB',NULL,NULL,NULL);

CREATE TABLE #Item
(
    Criteria1 VARCHAR(5),
    Criteria2 VARCHAR(5),
    Criteria3 VARCHAR(5),
    Criteria4 VARCHAR(5),
    Criteria5 VARCHAR(5),
);

INSERT INTO #Item
VALUES  ('AAA','AAB','AAC',NULL,NULL),
        ('AAB','AAC',NULL,NULL,NULL);

现在我已经设置了表格,这里是标准匹配。

 SELECT A.*,
        CASE WHEN A.Criteria1 = B.Criteria1 THEN 1 ELSE 0 END
        + CASE WHEN A.Criteria2 = B.Criteria2 THEN 1 ELSE 0 END
        + CASE WHEN A.Criteria3 = B.Criteria3 THEN 1 ELSE 0 END
        + CASE WHEN A.Criteria4 = B.Criteria4 THEN 1 ELSE 0 END
        + CASE WHEN A.Criteria5 = B.Criteria5 THEN 1 ELSE 0 END
        AS MatchingCriteria,
        B.ID AS ItemCriteriaID
FROM #Item A
INNER JOIN #ItemCriteria B
ON  A.Criteria1 = B.Criteria1
    OR A.Criteria2 = B.Criteria2
    OR A.Criteria3 = B.Criteria3
    OR A.Criteria4 = B.Criteria4
    OR A.Criteria5 = B.Criteria5
ORDER BY B.ID

结果:

Criteria1 Criteria2 Criteria3 Criteria4 Criteria5 MatchingCriteria ItemCriteriaID
--------- --------- --------- --------- --------- ---------------- --------------
AAA       AAB       AAC       NULL      NULL      2                1
AAB       AAC       NULL      NULL      NULL      1                2
AAB       AAC       NULL      NULL      NULL      1                3
AAA       AAB       AAC       NULL      NULL      2                4
AAA       AAB       AAC       NULL      NULL      1                5