2009-03-23 8 views
1

Le besoin basique est de savoir si un enregistrement a un attribut "Urgent", alors la valeur d'attribut doit être affichée dans la colonne Urgent. Si l'enregistrement a une valeur d'attribut "closed", alors la valeur d'attribut doit être affichée dans la colonne "Closed".Enregistrements unifiés pour la requête de base de données avec Sql

J'ai une requête ci-dessous. Mon problème est que parmi les résultats que je reçois, il y a deux enregistrements avec le même RequesterID (un avec une valeur valide dans la colonne "Urgent" et un avec une valeur dans la colonne "Closed") Mon problème est que j'ai besoin de ces deux enregistrements particuliers à afficher en un seul enregistrement.

Des idées?

SELECT DISTINCT 
    r.RequesterID, 
    sr.ModifiedDate, 
    p.FirstName + ' ' + p.LastName AS RequesterName, 
    CASE 
    WHEN sa.Attribute = 'Urgent' THEN sa.AttributeValue 
    ELSE NULL 
    END AS Urgent, 
    CASE 
    WHEN sa.Attribute = 'Closed' THEN sa.AttributeValue 
    ELSE NULL 
    END AS Closed 
FROM 
    Requester AS r 
    INNER JOIN SubRequester AS sr 
    ON r.RequesterID = sr.RequesterID 
    INNER JOIN SubRequesterAttribute AS sa 
    ON sr.SubRequesterID = sa.SubRequesterID 
    CROSS JOIN Personnel AS p 
WHERE 
    (r.UserID = p.ContractorID 
    OR r.UserID = p.EmployeeID) 
    AND 
    (sa.Attribute IN ('Urgent', 'Closed')) 
GROUP BY r.RequesterID, sr.ModifiedDate, p.FirstName, p.LastName, 
    sa.Attribute, sa.AttributeValue 
+0

Beaucoup de modifications ici. Désolé d'avoir tabassé certains d'entre eux. Que SQL avait juste besoin d'être formaté. – Welbog

Répondre

3

Vous devrez joindre deux fois la table attributaire de votre sous-requête à la requête. Un avec l'attribut Urgent et un avec l'attribut Close.

Vous devrez les joindre à gauche pour les instances où elles peuvent être nulles, puis référencer chacune des tables de votre SELECT pour afficher l'attribut relevent.

Je ne recommanderais pas non plus la jointure croisée. Vous devez effectuer votre jointure «OR» sur la table de personnel dans la clause FROM plutôt que d'effectuer une jointure croisée et un filtrage dans la clause WHERE.

EDIT: Désolé, ma première réponse a été un peu précipitée. Ont maintenant eu une chance de regarder plus loin. En raison du sous-requêteur et de l'attribut de sous-requête, les deux étant des doublons, vous devez les diviser en une sous-requête. En outre, votre date de modification pourrait être différente pour les deux valeurs. Donc j'ai doublé ça. Ceci est complètement non testé, et en aucun cas la solution "optimale". Il est assez difficile d'écrire la requête sans la base de données réelle à vérifier. J'espère que cela va expliquer ce que je voulais dire.

SELECT 
    r.RequesterID, 
    p.FirstName + ' ' + p.LastName AS RequesterName, 
    sra1.ModifiedDate as UrgentModifiedDate, 
    sra1.AttributeValue as Urgent, 
    sra2.ModifiedDate as ClosedModifiedDate, 
    sra2.AttributeValue as Closed 
FROM 
    Personnel AS p 
INNER JOIN 
    Requester AS r 
ON 
(
    r.UserID = p.ContractorID 
OR 
    r.UserID = p.EmployeeID 
) 
LEFT OUTER JOIN 
(
    SELECT 
     sr1.RequesterID, 
     sr1.ModifiedDate, 
     sa1.Attribute, 
     sa1.AttributeValue 
    FROM 
     SubRequester AS sr1 
    INNER JOIN 
     SubRequesterAttribute AS sa1 
    ON 
     sr1.SubRequesterID = sa1.SubRequesterID 
    AND 
     sa1.Attribute = 'Urgent' 
) sra1 
ON 
    sra1.RequesterID = r.RequesterID 
LEFT OUTER JOIN 
(
    SELECT 
     sr2.RequesterID, 
     sr2.ModifiedDate, 
     sa2.Attribute, 
     sa2.AttributeValue 
    FROM 
     SubRequester AS sr2 
    INNER JOIN 
     SubRequesterAttribute AS sa2 
    ON 
     sr2.SubRequesterID = sa2.SubRequesterID 
    AND 
     sa2.Attribute = 'Closed' 
) sra1 
ON 
    sra2.RequesterID = r.RequesterID 

EDIT SECOND: Ma dernière édition était qu'il y avait plusieurs SubRequesters ainsi que de multiples attributs, de votre dernier commentaire que vous voulez montrer tous les SubRequesters et les deux attributs relevent? Vous pouvez réaliser ceci comme suit.

SELECT 
    r.RequesterID, 
    p.FirstName + ' ' + p.LastName AS RequesterName, 
    sr.ModifiedDate, 
    sa1.AttributeValue as Urgent, 
    sa2.AttributeValue as Closed 
FROM 
    Personnel AS p 
INNER JOIN 
    Requester AS r 
ON 
(
    r.UserID = p.ContractorID 
OR 
    r.UserID = p.EmployeeID 
) 
INNER JOI N 
    SubRequester as sr 
ON 
    sr.RequesterID = r.RequesterID 
LEFT OUTER JOIN 
    SubRequesterAttribute AS sa1 
ON 
    sa1.SubRequesterID = sr.SubRequesterID 
AND 
    sa1.Attribute = 'Urgent' 
LEFT OUTER JOIN 
    SubRequesterAttribute AS sa2 
ON 
    sa2.SubRequesterID = sr.SubRequesterID 
AND 
    sa2.Attribute = 'Closed' 
+0

Je comprends votre 1er et 3e paragraphe. Cependant, je suis perdu sur votre 2ème paragraphe. Pouvez-vous expliquer un peu plus à ce sujet? – Csharp

+0

Pourquoi avez-vous créé un "sra1.ModifiedDate comme UrgentModifiedDate" ET "sra2.ModifiedDate comme ClosedModifiedDate"? Il n'y a qu'une seule colonne pour un champ de date. – Csharp

0

Généralement, si vous avez plusieurs lignes et que vous voulez les réduire en un, GROUP BY est l'outil de base pour y parvenir. On dirait que vous avez essayé d'aller dans cette direction mais n'y êtes pas tout à fait. Ce que vous voulez faire est de grouper par les expressions qui sont dupliquées entre les lignes, et appliquer des fonctions de groupe aux autres expressions qui élimineront les valeurs NULL. J'ai utilisé MIN dans l'exemple ci-dessous mais vous pouvez tout aussi bien utiliser MAX; le fait est que, puisque au plus une des lignes aura une valeur pour cette expression, cette valeur est à la fois le minimum et le maximum.

SELECT 
    r.RequesterID, 
    sr.ModifiedDate, 
    p.FirstName + ' ' + p.LastName AS RequesterName, 
    MIN(
    CASE 
    WHEN sa.Attribute = 'Urgent' THEN sa.AttributeValue 
    ELSE NULL 
    END 
    ) AS Urgent, 
    MIN(
    CASE 
    WHEN sa.Attribute = 'Closed' THEN sa.AttributeValue 
    ELSE NULL 
    END 
    ) AS Closed 
FROM 
    Requester AS r 
    INNER JOIN SubRequester AS sr 
    ON r.RequesterID = sr.RequesterID 
    INNER JOIN SubRequesterAttribute AS sa 
    ON sr.SubRequesterID = sa.SubRequesterID 
    CROSS JOIN Personnel AS p 
WHERE 
    (r.UserID = p.ContractorID 
    OR r.UserID = p.EmployeeID) 
    AND 
    (sa.Attribute IN ('Urgent', 'Closed')) 
GROUP BY r.RequesterID, sr.ModifiedDate, p.FirstName + ' ' + p.LastName