2009-12-03 3 views
2

J'ai une requête qui est supposée renvoyer la somme pour les entrées de "status" -duration. La durée est calculée en utilisant datediff (n, datestamp, (sous-requête qui renvoie le datestamp terminant l'état actuel, ie trouve le prochain ajustement "status change" -entry après celui verrouillé à)Requête SQL avec un problème d'identificateur en plusieurs parties au sein d'une sous-requête

Mon problème est que ce qui suit requête renvoie une erreur d'identification multi-partie

  • le tableau INC me donne la « INCIDENT_NUMBER » Je suis à la recherche Wich est lié à « NUMBER » dans les autres tableaux
  • ACTM1 détient tous DATESTAMP- Entrées
  • ACTA1 est associé à ACTM1 via "THENU MBER » et contient toutes les informations sur si une entrée est un changement d'état approprié ou non

code:

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 ... 

Je vous serais reconnaissant de tout commentaire utile ou laisser entendre que vous pourriez me donner sur ce ,

PS

Répondre

2

le côté gauche ne peut pas rejoindre relation de référence du côté droit, donc ce qui est illégal:

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

Utilisez le APPLIQUER opérateur à la place:

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

Dans votre cas serait probablement comme suit:

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 

Il est évident que le MIN dans la requête intérieure n'a pas de sens si.

+0

En fait, cela a du sens. Il y a parfois plus d'un "ajustement" des entrées de changement d'état. Ces entrées sont triées par "THENUMBER" dans l'ordre chronologique ... En tout cas merci pour votre aide. – Per

+0

Je ne parle pas d'un point de vue commercial, mais d'un point de vue SQL. Vous ne pouvez pas avoir des fonctions d'agrégation mélangées avec des champs non agrégées (ie. ACTM1_1_1.Number) withous un groupe par article. –

+0

Qu'est-ce que vous voulez sans doute est '(SELECT TOP (1) NUMÉRO, leNombre ... ORDER BY leNombre ASC)' –

1

Je réécrivaient la requête de ne pas utiliser les sous-requêtes du tout:

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 

je n'étais pas en mesure de concevoir entièrement votre déclaration inverse. Je ne sais pas si vous aviez besoin des jointures de gauche ou non et je n'ai pas vu où ACTA1 était réellement utilisé, alors je l'ai laissé de côté. Par conséquent, vous devrez peut-être modifier ce qui précède. L'idée générale est de se trouver une ligne avec un plus grand nombre, ce qui a le type que vous avez besoin, mais pour lesquels il n'y a pas d'autre rangée (A3) avec le bon type et un certain nombre qui se situe entre les deux nombres.

+0

Merci Tom, je vais essayer d'obtenir votre approche de travail. ACTA1 sera utilisé plus tard. Si une requête similaire fonctionnait sans le SUM au début. C'est de là que vient l'ACTA1. Le rapport dans lequel j'utilise cette requête le résume plus tard. Mais mon rapport actuel ne fonctionne pas de cette façon ... donc j'avais besoin de la somme dans ma requête. – Per

Questions connexes