首页 > 解决方案 > 结构化 SQL

问题描述

我有以下要求来生成报告。

TASKTYPE.TaskTypeName,TASKWIP.DMTaskState_key FROM MercuryProd.TEAMSPACE.F_DMCaseWIP WIP,
MercuryProd.TEAMSPACE.F_DMTaskWIP TASKWIP,
MercuryProd.TEAMSPACE.D_DMDataField_BM_ExternalCaseIdentifier EXTID,
MercuryProd.TEAMSPACE.D_DMTaskType TASKTYPE
WHERE WIP.DMCase_key=TASKWIP.DMCase_key
AND EXTID.BM_ExternalCaseIdentifier_key=WIP.VMAE_BM_ExternalCaseIdentifier_key
AND TASKTYPE.DMTaskType_key=TASKWIP.DMTaskType_key
AND EXTID.BM_ExternalCaseIdentifier='BMAX5C62970'
--AND TASKTYPE.DMTaskType_key=9 AND TASKWIP.DMTaskState_key=2
--AND TASKTYPE.DMTaskType_key=10 AND TASKWIP.DMTaskState_key=0

在此处输入图像描述

如果您查看 sql 的最后两行,这很关键。我需要满足这两个条件的所有记录。一个案例类型在 taskwip 表中可以有多个对应的子记录。我只需要过滤子记录中两个条件都满足的情况。那是状态为 2 的任务 9 和状态为 0 的任务 10。我在这里给出的是一个记录的示例数据。同样会有多个记录,例如另一个案例键,多个子记录,其中任务 9 的状态 3 不是 2,任务 10 的状态 2 不是 0。报告不应显示此记录。

如果您可以使用任何一种 DB 语言开发查询,无论是它的 slq 服务器、Oracle 还是 mysql,我都很高兴。我对逻辑比语言格式更感兴趣。

在此处输入图像描述

因为从结果集中可以看出,对于这个 case 键,有一个任务类型 10 的状态为 0,任务类型 9 的状态为 2。

标签: sqlsql-serveroracle

解决方案


规范不明确;我在猜测,这只是一个猜测,我们只想在两个特定行都存在的情况下返回行。

一种选择是在EXISTS谓词中使用相关子查询。

例如,像这样:

       TASKTYPE.TaskTypeName
     , TASKWIP.DMTaskState_key 

  FROM MercuryProd.TEAMSPACE.F_DMCaseWIP  WIP

  JOIN MercuryProd.TEAMSPACE.F_DMTaskWIP  TASKWIP
    ON TASKWIP.DMCase_key = WIP.DMCase_key

  JOIN MercuryProd.TEAMSPACE.D_DMDataField_BM_ExternalCaseIdentifier  EXTID
    ON EXTID.BM_ExternalCaseIdentifier_key = WIP.VMAE_BM_ExternalCaseIdentifier_key

  JOIN MercuryProd.TEAMSPACE.D_DMTaskType  TASKTYPE
    ON TASKTYPE.DMTaskType_key = TASKWIP.DMTaskType_key

 WHERE EXTID.BM_ExternalCaseIdentifier = 'BMAX5C62970'
   AND EXISTS ( SELECT 1
                  FROM MercuryProd.TEAMSPACE.D_DMTaskType  tt92 
                 WHERE tt92.DMTaskType_key     = 9
                   AND TASKWIP.DMTaskState_key = 2
              )
   AND EXISTS ( SELECT 1
                  FROM MercuryProd.TEAMSPACE.D_DMTaskType  tt10
                 WHERE tt10.DMTaskType_key     = 10
                   AND TASKWIP.DMTaskState_key = 0
              )

请注意,子查询返回什么值并不重要,EXISTS 只是检查是否至少返回一行。

请注意,这并不限制返回 TASKTYPE 中的哪些行。如果我们想将返回限制在特定的匹配行,我们可以添加到 TASKTYPE 连接的 ON 子句,或者添加到 WHERE 子句...

   AND (  ( TASKTYPE.DMTaskType_key = 9  AND TASKWIP.DMTaskState_key = 2 )
       OR ( TASKTYPE.DMTaskType_key = 10 AND TASKWIP.DMTaskState_key = 0 )
       )

我们可以使用其他查询模式;我们可以像这样做一个 EXISTS:

   AND EXISTS ( SELECT 1
                  FROM MercuryProd.TEAMSPACE.D_DMTaskType  ttx
                 WHERE ( ttx.DMTaskType_key = 9  AND TASKWIP.DMTaskState_key = 2 )
                    OR ( ttx.DMTaskType_key = 10 AND TASKWIP.DMTaskState_key = 0 )
                HAVING COUNT(DISTINCT ttx.DMTaskType_key) = 2
              )

编辑

演示的第一个模式是不够的。这要求两个 TASKTYPE 行都与同一个 TASKWIP 行相关,并且这不可能发生,因为每个 TASKTYPE 行都需要与 TASKWIP 行不同的值。

我们需要在相关子查询中进行连接。

这些方面的东西:

   AND EXISTS ( SELECT 1
                  FROM MercuryProd.TEAMSPACE.F_DMTaskWIP   tw92
                  JOIN MercuryProd.TEAMSPACE.D_DMTaskType  tt92 
                    ON tt92.DMTaskType_key   = tw92.DMTaskType_key
                   AND tt92.DMTaskType_key   = 9
                 WHERE tw92.DMTaskState_key  = 2
                   AND tw92.DMCase_key       = WIP.DMCase_key
              )
   AND EXISTS ( SELECT 1
                  FROM MercuryProd.TEAMSPACE.F_DMTaskWIP   tw10
                  JOIN MercuryProd.TEAMSPACE.D_DMTaskType  tt10
                    ON tt10.DMTaskType_key   = tw10.DMTaskType_key
                   AND tt10.DMTaskType_key   = 10
                 WHERE tw10.DMTaskState_key  = 0
                   AND tw10.DMCase_key       = WIP.DMCase_key
              )

推荐阅读