SQL-consulta com um problema identificador de várias partes dentro de uma subconsulta
-
12-09-2019 - |
Pergunta
Eu tenho uma consulta que deve retornar a soma de entradas -Duração "status". A duração é calculada usando datediff (n, data-hora, (subconsulta que retorna do carimbo datador terminando o estado actual, isto é encontra da próxima encaixe "mudança de estado" -Entrada depois a uma bloqueada no)
Meu problema é que a consulta a seguir retorna um erro identificador de várias partes
- A tabela INC está me dando o "INCIDENT_NUMBER" eu estou procurando wich está relacionada com "Número" nas outras tabelas
- ACTM1 detém todo DATESTAMP-entradas
- ACTA1 está relacionada com ACTM1 via "oNumero" e que detém todas as informações sobre se uma entrada é uma mudança de status apropriado ou não
Código:
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 ...
Eu ficaria grato por qualquer comentário útil ou dica que você poderia me dar sobre este assunto,
PS
Solução
O lado esquerdo juntar a relação não pode referenciar o lado direito, então isso é ilegal:
SELECT ...
FROM A
JOIN (SELECT ...FROM ... WHERE ... = A.Field) AS B ON A.ID = B.ID;
Use o operador aplicar em seu lugar:
SELECT ...
FROM A
APPLY (SELECT ...FROM ... WHERE ... = A.Field AND ID = A.ID) AS B;
No seu caso provavelmente seria como seguir:
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
Obviamente, o MIN dentro da consulta interna não faz sentido embora.
Outras dicas
Eu reescrever a consulta para não usar subconsultas em tudo:
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
Eu não era capaz de projetar totalmente inversa a sua declaração. Eu não sei se você precisava de esquerda junta-se ou não, e eu não vi onde ACTA1 foi realmente sendo usado, então eu deixei-o para fora. Como resultado, pode ser necessário ajustar o acima. A idéia geral é que para encontrar uma linha com um número maior, que tem o tipo que você precisa, mas para os quais não há outra linha (A3) com o tipo certo e um número que cai entre os dois números.