SQL-Query с проблемой множественного идентификатора в подзапросе - PullRequest
2 голосов
/ 03 декабря 2009

У меня есть запрос, который должен вернуть сумму для записей о статусе. Продолжительность вычисляется с использованием datediff (n, datetamp, (подзапрос, который возвращает метку даты, заканчивающую текущее состояние, то есть находит следующую подходящую запись «изменение статуса» после того, что заблокирован в)

Моя проблема заключается в том, что следующий запрос возвращает ошибку, состоящую из нескольких частей

  • Таблица INC дает мне "INCIDENT_NUMBER" я ищу, который связан с «НОМЕР» в других таблицах
  • ACTM1 содержит все записи DATESTAMP
  • ACTA1 связан с ACTM1 через «THENUMBER» и содержит всю информацию о том, является ли запись подходящим изменением статуса или нет

Код:

SELECT SUM(DATEDIFF(n, ACTM1.DATESTAMP, END_DATESTAMP_TABLE.END_DATESTAMP))
FROM INC                LEFT OUTER JOIN
  ACTM1   ON INC.INCIDENT_NUMBER = ACTM1.NUMBER  LEFT OUTER JOIN
  ACTA1   ON ACTM1.THENUMBER  = ACTA1.THENUMBER  LEFT OUTER JOIN
/**/
    (SELECT  ACTM1_1.NUMBER, ACTM1_1.DATESTAMP AS END_DATESTAMP
  FROM ACTM1 AS ACTM1_1               LEFT OUTER JOIN
/**/
      (SELECT ACTM1_1_1.NUMBER, MIN(ACTM1_1_1.THENUMBER) AS FOLLOWUP_THENUMBER
    FROM ACTM1 AS ACTM1_1_1
    WHERE  (ACTM1_1_1.THENUMBER > /**/ ACTM1_1.THENUMBER)/*I think here lies the problem*/
      AND (ACTM1_1_1.[TYPE]  IN ('Open', 'Status Change', 'Resolved', 'Closed')))
    AS FOLLOWUP_THENUMBER_TABLE
/**/
            ON ACTM1_1.NUMBER = FOLLOWUP_THENUMBER_TABLE.NUMBER)
  AS END_DATESTAMP_TABLE
/**/
            ON ACTM1.NUMBER = END_DATESTAMP_TABLE.NUMBER
WHERE ...

Буду признателен за любые полезные комментарии или подсказки, которые вы могли бы дать мне по этому поводу,

PS

Ответы [ 2 ]

2 голосов
/ 03 декабря 2009

Отношение соединения левой стороны не может ссылаться на правую сторону, поэтому это недопустимо:

SELECT ...
FROM A
JOIN (SELECT ...FROM ... WHERE ... = A.Field) AS B ON A.ID = B.ID;

Вместо этого используйте оператор APPLY:

SELECT ...
FROM A
APPLY (SELECT ...FROM ... WHERE ... = A.Field AND ID = A.ID) AS B;

В вашем случае, вероятно, будет выглядеть следующее:

SELECT SUM(DATEDIFF(n, ACTM1.DATESTAMP, END_DATESTAMP_TABLE.END_DATESTAMP))
FROM INC                
LEFT OUTER JOIN ACTM1 ON INC.INCIDENT_NUMBER = ACTM1.NUMBER  
LEFT OUTER JOIN ACTA1 ON ACTM1.THENUMBER  = ACTA1.THENUMBER  
LEFT OUTER JOIN (
   SELECT  ACTM1_1.NUMBER, ACTM1_1.DATESTAMP AS END_DATESTAMP
   FROM ACTM1 AS ACTM1_1
   OUTER APPLY (
      SELECT ACTM1_1_1.NUMBER, /* MIN(ACTM1_1_1.THENUMBER) */ AS FOLLOWUP_THENUMBER
        FROM ACTM1 AS ACTM1_1_1
        WHERE  (ACTM1_1_1.THENUMBER > ACTM1_1.THENUMBER)
        AND (ACTM1_1.NUMBER = FOLLOWUP_THENUMBER_TABLE.NUMBER)
        AND (ACTM1_1_1.[TYPE]  IN ('Open', 'Status Change', 'Resolved', 'Closed'))
    ) AS FOLLOWUP_THENUMBER_TABLE
) AS END_DATESTAMP_TABLE ON ACTM1.NUMBER = END_DATESTAMP_TABLE.NUMBER

Очевидно, что MIN во внутреннем запросе не имеет смысла.

1 голос
/ 03 декабря 2009

Я бы переписал запрос, чтобы вообще не использовать подзапросы:

SELECT
     SUM(DATEDIFF(n, A1.datestamp, A2.datestamp))

FROM
     INC AS I
INNER JOIN ACTM1 AS A1 ON
     A1.number = INC.incident_number
INNER JOIN ACTM1 AS A2 ON
     A2.number > A1.number AND
     A2.type IN ('Open', 'Status Change', 'Resolved', 'Closed')
LEFT OUTER JOIN ACTM1 AS A3 ON
     A3.number > A1.number AND
     A3.type IN ('Open', 'Status Change', 'Resolved', 'Closed') AND
     A3.number < A2.number
WHERE
     A3.number IS NULL

Я не смог полностью перепроектировать ваше утверждение. Я не знаю, нужны ли вам левые соединения или нет, и я не видел, где фактически использовался ACTA1, поэтому я оставил это. В результате вам может понадобиться настроить вышеперечисленное. Общая идея заключается в том, чтобы найти строку с большим номером, имеющего нужный вам тип, но для которого нет другой строки (A3) с правильным типом и числом, которое находится между двумя числами. *

...