我在网上找到了以下脚本的改编版本:
CREATE TABLE alphaCodes
(personID INTEGER NOT NULL,
codes CHAR(10) NOT NULL,
);
INSERT INTO alphaCodes
VALUES (1, '12300'), (1, '23400'), (1, '45623'),
(2, '99900'), (2, '23411'), (2, '78900'),
(3, '12300'), (3, '23400'), (3, '45699');
go
CREATE PROCEDURE GetPeopleWithCodes
(@d1 CHAR(10) = NULL, @d2 CHAR(10) = NULL,
@d3 CHAR(10) = NULL, @d4 CHAR(10) = NULL,
@d5 CHAR(10) = NULL)
AS BEGIN
--cte for the alphaCodes table
WITH Patient_Diagnosis (personID, codes)
AS (SELECT personID, codes FROM alphaCodes),
codeList (codePattern)
AS
--row constructor makes a table of the variables that will be passed into the stored procedure
(SELECT X.codePattern
FROM (VALUES (@d1), (@d2), (@d3), (@d4), (@d5))
AS X(codePattern)
WHERE X.codePattern IS NOT NULL)
SELECT DISTINCT personID
FROM Patient_Diagnosis AS PD1
WHERE NOT EXISTS
(SELECT *
FROM codeList
WHERE NOT EXISTS
(SELECT *
FROM Patient_Diagnosis AS PD2
WHERE PD1.personID = PD2.personID
AND PD2.codes LIKE codeList.codePattern));
END;
--for whatever reason, the % wildcard does not and and the _ has to be used
exec dbo.GetPeopleWithCodes '123___'
此存储过程最多需要五个输入参数,并且基本上会返回您包含的许多参数的内部联接。所以,如果你运行
exec dbo.getpeoplewithcodes '234___'
1,2,3
将被退回。如果你运行
exec dbo.getpeoplewithCodes '234____','123___'
将返回1,3
。当我尝试这样做时,我使用动态SQL创建了一个包含各种连接到alphaCodes
表的表。上面的方法比较快,但有一个问题:我不能为我的生活完全理解它。我喜欢上次连接中的like
运算符,但我没有得到第一个where not exists
子查询。谁能帮忙解释一下发生了什么?你怎么能只有两个引用alphaCodes表并让这个东西仍然有效?
答案 0 :(得分:1)
如果我已正确理解,此代码旨在返回所有诊断代码与所有输入参数模式匹配的患者列表。
最后的SELECT
语句是一个双重否定,表示相同的要求 - 它返回不在Patient_Diagnosis.Patient_Id
行集合中的行中所有Patient_Diagnosis
值的不同列表没有与输入参数列表匹配的代码。这是编写此查询的一种令人困惑的方式。
以下未经过严格测试,但只显示alphaCodes
表的一次扫描,似乎返回相同的结果。我已经删除alphaCodes
上的CTE,因为它是多余的:
ALTER PROCEDURE GetPeopleWithCodes
(@d1 CHAR(10) = NULL, @d2 CHAR(10) = NULL,
@d3 CHAR(10) = NULL, @d4 CHAR(10) = NULL,
@d5 CHAR(10) = NULL)
AS BEGIN
WITH codeList (codePattern)
AS
(SELECT X.codePattern
FROM (VALUES (@d1), (@d2), (@d3), (@d4), (@d5))
AS X(codePattern)
WHERE X.codePattern IS NOT NULL
)
SELECT pd.PersonId
FROM codeList cl
JOIN alphaCodes pd
ON pd.codes LIKE cl.codePattern
GROUP BY pd.personID
HAVING COUNT(*) = (SELECT COUNT(*) FROM codeList)
END
GO