我正在尝试创建一个存储过程,该存储过程返回person表中具有特定列相同值的行。我希望存储过程接受@match_on_forenames BIT
和@match_on_surname BIT
等参数值。因此,例如EXEC find_matching @match_on_forenames 1, @match_on_surname 1
会在表中找到名称和姓氏字段匹配的行,显然不匹配自身。
我的存储过程类似于:
ALTER PROC get_matching_records
@match_on_forenames BIT,
@match_on_surname BIT
AS
SELECT DISTINCT
p.forenames, p.surname
FROM
person p
WHERE
EXISTS
(
SELECT
p1.forenames, p1.surname
FROM
person p1
WHERE
(((@match_on_forenames = 1 AND p.forenames = p1.forenames AND p.id <> p1.id)) OR @match_on_forenames = 0)
AND (((@match_on_surname = 1 AND p.surname = p1.surname AND p.id <> p1.id)) OR @match_on_surname = 0)
)
当我介绍OR @match_on_forenames
时,查询的性能变得非常差。
我最好如何处理这个问题?
非常感谢。
答案 0 :(得分:0)
这是你的逻辑:
WHERE EXISTS (SELECT 1
FROM person p1
WHERE
(((@match_on_forenames = 1 AND p.forenames = p1.forenames AND p.id <> p1.id)) OR @match_on_forenames = 0)
AND (((@match_on_surname = 1 AND p.surname = p1.surname AND p.id <> p1.id)) OR @match_on_surname = 0)
)
如果在没有or
的情况下很快,那么有三个条件可以解决问题:
WHERE (@match_on_forenames = 1 and @match_on_surname = 1 and
EXISTS (SELECT 1
FROM person p1
WHERE (p.forenames = p1.forenames AND p.id <> p1.id) AND
(p.surname = p1.surname AND p.id <> p1.id)
)
) OR
(@match_on_forenames = 0 and @match_on_surname = 1 and
EXISTS (SELECT 1
FROM person p1
WHERE (p.surname = p1.surname AND p.id <> p1.id)
)
) OR
(@match_on_forenames = 1 and @match_on_surname = 0 and
EXISTS (SELECT 1
FROM person p1
WHERE (p.forenames = p1.forenames AND p.id <> p1.id)
)
)
根据您对更简单查询更快的观察,每个exists
子句都应该很快。
答案 1 :(得分:0)
我通常避免在我的SQL语句中使用OR 这是我要做的,在同一张桌子上使用JOIN。
SELECT DISTINCT
p.forenames, p.surname
FROM
person p
inner join person pmatch on
pmatch.id <> p.id
and
case when @match_on_forenames =1 then pmatch.forenames else p.forenames end = p.forenames
and
case when @match_on_surname =1 then pmatch.surname else p.surname end = p.surname