Sql server 具有可选参数的存储过程不显示联接表的空值

Sql server 具有可选参数的存储过程不显示联接表的空值,sql-server,stored-procedures,reporting-services,left-join,optional-parameters,Sql Server,Stored Procedures,Reporting Services,Left Join,Optional Parameters,我环顾四周,找到了解决这个问题的各种方法,但没有一种在我的具体情况下有效。我编写了一个存储过程,用于SSRS报告,其中包含可选参数(在SSRS中,我指定了一个可用参数列表,以及一个“All”选项,其中值设置为“=Nothing”)。如果未选择任何选项,则显示所有记录时,这适用于容纳多个可选参数。。。除了那些具有空ProjectID值的 我希望能够运行存储过程并为@Project参数指定“Null”,并显示带有Null ProjectID字段的值,理想情况下,为该参数的SSRS报告添加一个“Non

我环顾四周,找到了解决这个问题的各种方法,但没有一种在我的具体情况下有效。我编写了一个存储过程,用于SSRS报告,其中包含可选参数(在SSRS中,我指定了一个可用参数列表,以及一个“All”选项,其中值设置为“=Nothing”)。如果未选择任何选项,则显示所有记录时,这适用于容纳多个可选参数。。。除了那些具有空ProjectID值的

我希望能够运行存储过程并为@Project参数指定“Null”,并显示带有Null ProjectID字段的值,理想情况下,为该参数的SSRS报告添加一个“None”选项,该选项也将显示这些值

我不太确定如何修改SP以实现这一点:

ALTER PROCEDURE [dbo].[TasksByStatus]

@Status AS Integer = NULL,
@Project AS Integer = NULL

AS

BEGIN

SELECT Task, CONVERT(VARCHAR, StartDate, 101) AS StartDate, 
      (CASE WHEN CompleteDate IS NULL THEN 'Not complete yet' 
       ELSE CONVERT(VARCHAR, CompleteDate, 101) END) AS CompleteDate, 
      (CASE WHEN Notes IS NULL THEN 'No notes provided' ELSE Notes END) AS Notes, 
       ProjectName, StatusName
FROM Tasks 
INNER JOIN Status ON Tasks.StatusID = Status.ID
LEFT JOIN Projects ON Tasks.ProjectID = Projects.ID 
AND Projects.ID IS NULL

WHERE Status.ID = ISNULL(@Status, Status.ID) 
AND Projects.ID = ISNULL(@Project, Projects.ID)
ORDER BY StartDate, StatusName

END
未指定参数的查询结果:

在为@Project指定NULL时,我的意图是只查看具有NULL ProjectID值的一条记录

编辑以进一步澄清

若要操作,请让我们知道给定表格中每行的确切结果。另外,当您提到“无”时,您希望如何将其传递给存储过程?(@Project变量定义为整数)


如果您想在
产品上
左连接
,那么您需要在
上的
而不是
的WHERE
中包含该子句。将它放在
的位置
使其成为
内部连接

ALTER PROCEDURE [dbo].[TasksByStatus]
  @Status  INT = NULL,
  @Project INT = NULL
AS
BEGIN
  SET NOCOUNT ON;

  SELECT 
    Task, 
    CONVERT(VARCHAR, StartDate, 101) AS StartDate, 
    (CASE WHEN CompleteDate IS NULL THEN 'Not complete yet' 
     ELSE CONVERT(VARCHAR, CompleteDate, 101) END) AS CompleteDate, 
    (CASE WHEN Notes IS NULL THEN 'No notes provided' ELSE Notes END) AS Notes, 
    ProjectName, StatusName
  FROM dbo.Tasks 
  INNER JOIN dbo.Status ON Tasks.StatusID = Status.ID
  LEFT JOIN dbo.Projects ON Tasks.ProjectID = Projects.ID 
  WHERE Status.ID = COALESCE(@Status, Status.ID) 
    AND COALESCE(Projects.ID, -1) = COALESCE(@Project, Projects.ID, -1)
  ORDER BY StartDate, StatusName;
END
GO

这种查询是灾难的捷径。请记住,SQL必须编译适用于任何参数值的查询计划。因此,即使指定了@Project和/或@Status,它也将被迫在
Status
Projects
表上执行表扫描!Erland Sommarskog将在

将其分为3个不同的查询:

if (@Status is null and @Project is null)
   select ...;
else if (@status is null)
   select ... where ProjectID = @Project;
else if (@project is null)
   select ... where StatusID = @status;
else
   select ... where StatusID = @status and ProjectID = @Project;

您的查询既有
又有Projects.ID为NULL
又有
和Projects.ID=ISNULL(@Project,Projects.ID)
。这些不矛盾吗?是的,我也发现了。我删除了“AND Projects.ID为空”。我用它进行测试。不幸的是,合并方法并没有改变结果。@Zogglet-我相信您正在尽最大努力,但缺少答案清楚地告诉我,很多人对您的要求有困难。我在你的答案上加了一张正确的表格。我已经填写了你的真值表,为了回答你关于传递“无”的问题,我指的是这个存储过程作为SSRS中使用的数据集的实现。我在可用参数中添加了一个值为NULL的“None”选项。但是,我有另一个“All”选项,它将=Nothing传递给参数,该参数成功地显示了除ProjectID为null值的记录之外的所有记录。这就是问题所在。这能澄清什么吗?谢谢。这实际上显示了这些字段,但将NULL传递给@Project也会返回所有其他值,而不仅仅是那些ProjectID值为NULL的值。在仍然允许该参数是可选的情况下,有没有一种方法可以做到这一点,比如,不向其传递值,而向其传递NULL?您需要显示样本数据和所需结果,无论有无NULL参数。很抱歉,我遇到了文字问题。使用NULL参数:仅当记录的ProjectID字段为NULL时,才返回包含Task、StartDate、CompletedDate、Notes、ProjectName和StatusName的记录。不带NULL参数:使用指定的@Status参数显示所有记录,或者,如果未提供该参数,则显示所有记录。请立即尝试,假设
Projects.ID
始终为正值。如果这仍然不能产生你想要的结果,请在问题中添加示例数据和期望的结果。我道歉。您希望我如何在这些评论的上下文中提供示例数据和结果?这是一段非常糟糕的代码。如果表的大小成为一个问题,我宁愿使用动态SQL并依靠特殊计划绕过优化器。@Aaron:是的,也许动态SQL比维护4种形式的查询要好,尽管维护动态SQL生成代码可能更难排除故障是有争议的。我的主要观点是,这种各行各业的质疑是一场正在酝酿中的灾难。最终,问题在于应用程序设计中选择创建一个显然执行4个不同任务的API,而不是创建4个不同的API。这只是一个糟糕的API设计,但我很久以前就放弃了在论坛上解决这个问题。。。
if (@Status is null and @Project is null)
   select ...;
else if (@status is null)
   select ... where ProjectID = @Project;
else if (@project is null)
   select ... where StatusID = @status;
else
   select ... where StatusID = @status and ProjectID = @Project;