0

我在网上找到了以下脚本的改编:

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 表并且让这个东西仍然有效?

4

1 回答 1

1

如果我理解正确,此代码旨在返回所有患者的列表,这些患者的诊断代码与所有输入参数模式匹配。

最后的SELECT语句是一个双重否定,说明了相同的要求 - 它返回一个不同的列表,其中包含所有行的Patient_Diagnosis.Patient_Id值,这些Patient_Diagnosis行不在没有与输入参数列表匹配的代码的行集中。这是编写此查询的一种令人困惑的方式。

以下内容没有经过大量测试,但似乎仅通过一次扫描alphaCodes表即可返回相同的结果。我已经删除了 CTE,alphaCodes因为它是多余的:

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
于 2012-12-10T22:07:16.133 回答