有没有一种方法可以在过程的WHERE子句中使用条件“ IN”语句?

时间:2020-03-25 22:32:22

标签: sql tsql

比方说,我有一个名为“学生”的表格,其中包含以下列:名字,姓氏,成绩。现在,假设我有一个名为“ getStudents”的过程,您可以在其中传递以逗号分隔的成绩列表供您选择。看起来像这样:

CREATE PROCEDURE [dbo].[getStudents] (
@GradeList VARCHAR(MAX)
)
AS
BEGIN
     --Declare temporary table for grades
     CREATE TABLE #Grades (Grade varchar(50))

     --Insert the grades from @GradeList parameter into the temp table
     INSERT INTO
          #Grades
     SELECT value AS Grade
     FROM
          --This is a function that will split the comma delimited list and return the values
          [dbo].[SplitValues] (@GradeList)

     --Select all students that are in the grades provided
     SELECT
          FirstName,
          LastName
     FROM
          Student
     WHERE
          Grade IN (SELECT Grade FROM #Grades)
END

这一切都按预期进行。但是我们现在想要的是使@GradeList为可选参数,如果它的值为NULL,那么我们想返回所有学生。在这个简化的示例中,我只是执行IF语句,但实际上我们希望具有多个可选参数,因此它必须是同一SELECT语句的一部分。我能够按照以下逻辑进行操作:

CREATE PROCEDURE [dbo].[getStudents] (
@GradeList VARCHAR(MAX) = NULL
)
AS
BEGIN
     --Declare temporary table for grades
     CREATE TABLE #Grades (Grade varchar(50))

     --Insert list of grades into a temporary table
     IF @GradeList IS NULL
     BEGIN
          --No grades provided, select all possible values for Grade into temp table
          INSERT INTO
               #Grades
          SELECT DISTINCT
               Grade
          FROM
               Student
     END
     ELSE
     BEGIN
          --Insert the grades from @GradeList parameter into the temp table
          INSERT INTO
               #Grades
          SELECT value AS Grade
          FROM
               --This is a function that will split the comma delimited list and return the values
               [dbo].[SplitValues] (@GradeList)
     END

     --Select all students that are in the grades provided
     SELECT
          FirstName,
          LastName
     FROM
          Student
     WHERE
          Grade IN (SELECT Grade FROM #Grades)
END

因此,如果没有传入任何内容,我只需将Grade的所有可能值添加到#Grades临时表中。从功能上来说,这是可行的,并且正在做我们想要做的事情。但是,由于我们在这里处理大型表,因此增加了该过程的大量开销(现在要花大约一分钟的时间才能运行,大约需要1-2秒)。有没有一种方法可以让WHERE子句中的条件取决于@GradeList是否有值?

1 个答案:

答案 0 :(得分:2)

我想你想要

a + (a-b)/c*c

无需使用临时表来存储结果。您可以直接在查询中使用SELECT s.FirstName, s.LastName FROM Student s WHERE s.Grade IN (SELECT g.Grade FROM #Grades g) OR @GradeList IS NULL; 。但是,如果您确实使用临时表,则最好充分利用它。将split_string()定义为主键:

Grade

这为优化以后的查询提供了更多机会。