【问题标题】:Return result from query even if WHERE clause not met即使未满足 WHERE 子句,也从查询返回结果
【发布时间】:2014-10-21 05:38:01
【问题描述】:

我正在创建一个查询,以确保满足某些约束。这是一个半工作版本:

SELECT CASE
            WHEN TaskId IS NULL THEN 0
            ELSE 1  
        END AS TaskExists, 
        CASE
            WHEN IsDownTask = 0 AND TaskStatus = 63 THEN 1
            WHEN IsDownTask = 1 THEN 1
            ELSE 0
        END AS PressReady,
        CASE 
            WHEN IsDownTask = 1 AND MachineId <> 2710 THEN 1
            ELSE 0
        END AS DownTaskAssignedToDifferentMachine   
FROM Task T
WHERE TaskId = 555555

当TaskId 存在于Task 表中时,这可以正常工作,但如果该任务不存在(因此TaskExists 字段),我还需要返回值。

对于不存在的任务的查询,我希望返回

  • TaskExists 0
  • PressReady 0
  • DownTaskAssignedToDisfferentMachine 0

即使不存在TaskId,我如何修改我的查询以返回它?

【问题讨论】:

  • 当taskId 在此表中不存在时,它还存在于何处?
  • 这可以使用一个相当丑陋的 SQL 语句来完成。如果我是你,我会留下这样的 SQL 并在 C# 端实现一个Null Object,它具有你列举的属性。如果 SQL 没有返回结果,我会使用 null 对象
  • TaskId 在这个表中是唯一的吗?
  • TaskId 来自用户输入。如果他们粗心大意,我想确保我可以提供一些我们不知道的关于任务的反馈。 TaskId 在 Task 表中是唯一的,是的。我现在更倾向于查询 Task 对象并检查客户端是否为 null 和其余属性...

标签: sql sql-server ibatis.net


【解决方案1】:

如果您想返回这些值,只需用 SUM 和 ISNULL 包装每一列:

SELECT ISNULL(SUM(CASE
        WHEN TaskId IS NULL THEN 0
        ELSE 1  
    END), 0) AS TaskExists, 
    ISNULL(SUM(CASE
        WHEN IsDownTask = 0 AND TaskStatus = 63 THEN 1
        WHEN IsDownTask = 1 THEN 1
        ELSE 0
    END), 0) AS PressReady,
    ISNULL(SUM(CASE 
        WHEN IsDownTask = 1 AND MachineId <> 2710 THEN 1
        ELSE 0
    END), 0) AS DownTaskAssignedToDifferentMachine    

【讨论】:

  • 我只会用count(TaskId) 代替TaskExists。
  • Count 也可以,也可以让我们消除 case 表达式。好主意。
  • 是的,这就像我想要的那样工作。我建议进行编辑以将ISNULL 检查添加到最后两个字段。否则他们返回NULL,我想避免从数据库返回可为空的整数。
【解决方案2】:

你可以试试这样的:

DECLARE @task INT
SET @task = 555555

SELECT CASE
            WHEN TaskId IS NULL THEN 0
            ELSE 1  
        END AS TaskExists, 
        CASE
            WHEN IsDownTask = 0 AND TaskStatus = 63 THEN 1
            WHEN IsDownTask = 1 THEN 1
            ELSE 0
        END AS PressReady,
        CASE 
            WHEN IsDownTask = 1 AND MachineId <> 2710 THEN 1
            ELSE 0
        END AS DownTaskAssignedToDifferentMachine   
FROM Task T
WHERE TaskId = @task
UNION ALL 
SELECT 0 TaskExists, 0 PressReady, 0 DownTaskAssignedToDifferentMachine   
WHERE NOT EXISTS (SELECT * FROM  Task WHERE TaskId = @task)

【讨论】:

    【解决方案3】:

    如果它必须在查询中,而不是在代码中,那么只需作弊并将默认行添加到查询的末尾即可。保证默认排序在任何可能的真实结果之后,并限制在您的第一行:

    SELECT TOP 1 * FROM (
      SELECT 1 AS TaskExists, CASE ... END AS PressReady, CASE ... AS WowYouHaveALongFieldNameHere
        FROM Task
       WHERE TaskID = 55555
    
      UNION
    
      -- default if no matching row
      SELECT 0,               0,                          0
    ) ORDER BY TaskExists DESC;
    

    您可能会发现这比涉及聚合函数或强制连接和 COALESCE/ISNULLing 等的替代方案更具可读性。

    【讨论】:

      【解决方案4】:

      请尝试以下代码。我没有测试过。

      SELECT CASE
                      WHEN TaskId IS NULL THEN 0
                      ELSE 1  
                  END AS TaskExists, 
                  CASE
                      WHEN IsDownTask = 0 AND TaskStatus = 63 THEN 1
                      WHEN IsDownTask = 1 THEN 1
                      ELSE 0
                  END AS PressReady,
                  CASE 
                      WHEN IsDownTask = 1 AND MachineId <> 2710 THEN 1
                      ELSE 0
                  END AS DownTaskAssignedToDifferentMachine   
          FROM Task T
          WHERE  1= case when TaskId = 555555 then 1 
          else 0 end 
      

      【讨论】:

      • 建议对此进行修改:您的 ELSE 是 'o' 而不是零。将其标记为未经测试很好,但将来可能值得花额外的时间在发布之前先测试您的答案 - 更高质量的答案,即使迟到几分钟,也比发布带有问题。
      猜你喜欢
      • 2018-10-14
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多