Структурирование SQL - PullRequest
       1

Структурирование SQL

1 голос
/ 03 апреля 2020

У меня есть следующее требование для создания отчета.

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

enter image description here

Если вы посмотрите на последние две строки sql, это важно Мне нужны все записи, удовлетворяющие обоим условиям. Тип дела может иметь несколько соответствующих дочерних записей в таблице задач. Мне нужно отфильтровать только те случаи, когда в дочерних записях встречаются оба критерия. Это задача 9 с состоянием 2 и задача 10 с состоянием 0. Здесь я привел пример данных для одной записи. Аналогично, будет несколько записей, как для другого ключа дела, несколько дочерних записей, где задача 9 с состоянием 3 не 2 и задача 10 с состоянием 2 не 0. Отчет не должен показывать эту запись.

Я рад, если вы сможете разработать запрос на любом языке БД, будь то его сервер slq, Oracle, mysql. Меня интересует больше логика c, чем языковой формат.

enter image description here

Поскольку, как видно из набора результатов, для этого ключа дела, есть тип задачи 10 с состоянием 0 и тип задачи 9 с состоянием 2.

Ответы [ 2 ]

2 голосов
/ 03 апреля 2020

Спецификация не ясна; Я предполагаю, и это всего лишь предположение, что мы хотим возвращать строки ТОЛЬКО, если ОБА из пары существует c строк.

Один из вариантов - использовать коррелированные подзапросы в предикате 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. Если мы хотим ограничить возврат только указанием c совпадающих строк, мы можем добавить к предложению ON соединения TASKTYPE или к предложению WHERE ...

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

Есть другие шаблоны запросов, которые мы могли бы использовать; мы могли бы сделать один СУЩЕСТВУЮЩИЙ, как это:

   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
              )
0 голосов
/ 03 апреля 2020

Для oracle вы можете использовать список, как показано ниже

   SELECT DM_Case_Key,listagg(TaskTypeName,',') within group (order by DMTaskType_key)
   over (partition by DM_Case_Key) as Tasks
   FROM your_data   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...