2017-02-09 3 views
0

J'ai une table project p et une table invoice i, les deux ont un champ project_id. Je veux un jeu de résultats qui comprend tous les project_ids de projecti.status = "Active" et qui comprend également tous les project_ids de invoiceinvoice_date > 2016-01-01. Voici la requête que j'ai essayée jusqu'ici.SQL OUTER JOIN renvoyant des enregistrements vides - pourquoi?

SELECT 
    p.project_id 
FROM 
    (SELECT project_id 
     FROM project 
     WHERE status = 'Active') p 
FULL OUTER JOIN 
    (SELECT DISTINCT project_id 
     FROM invoice 
     WHERE CONVERT(varchar(10),invoice_date, 20) > '2016-01-01') i 
ON i.project_id = p.project_id 

Il y a environ 80 projets en projects avec le statut = actif et environ 120 projets dans invoice qui ont été facturés depuis 01.01.2016. La requête ci-dessus renvoie environ 140 enregistrements, ce qui sonne bien (certains projets actifs non facturés et certains projets facturés non actifs). Le problème est que la requête a environ la moitié des project_ids comme vide (NULL?). C'est comme si ça ne tirait pas les project_ids de invoice. S'il vous plaît, aidez-moi à corriger cela.

Voici un court segment du jeu de résultats comme un tableau ...

... 
[10] => Array 
    (
     [project_id] => 
    ) 

[11] => Array 
    (
     [project_id] => C00F2097-CD36-4497-8B26-0BF59F90B1EA 
    ) 

[12] => Array 
    (
     [project_id] => 217F3370-50F2-457E-A4F5-0C09F12E654A 
    ) 

[13] => Array 
    (
     [project_id] => 
    ) 

[14] => Array 
    (
     [project_id] => B1A06823-73C8-4691-A3D6-0E1A234516B3 
etc... 
+0

parce que ce sont les projets où ils sont «actifs», mais n'ont pas un projet correspondant de la facture où 'invoice_date> '2016-01-01''. Et vous pourriez avoir des cas où il n'y a pas de projets 'active' pour les factures – Lamak

+0

Inclure les deux tables valeur du projet dans votre sélection. Je suis également perplexe pourquoi vous comparez "dates" à une valeur de chaîne? Je suppose que ça marchera puisque c'est le format aaaa-mm-jj; mais il me semble plus sûr de comparer les dates en utilisant un datatype de date. – xQbert

Répondre

2

changement

SELECT coalesce(p.project_id, i.project_id) as project_id 

et vous n'avez des valeurs nulles. Les valeurs nulles sont celles de la facture mais pas du projet.

+1

La réponse de Gordan est meilleure, mais je vais laisser cela dans l'espoir qu'il vous aide à comprendre quel était le problème. – Hogan

3

Votre description ne fait que hurler "utiliser UNION, utiliser UNION"!

SELECT p.project_id 
FROM project p 
WHERE p.status = 'Active' 
UNION -- On purpose to remove duplicates 
SELECT i.project_id 
FROM invoice i 
WHERE i.invoice_date > '2016-01-01'; 

Remarque: Il n'est pas nécessaire de convertir une date en chaîne pour la comparer à une valeur constante. En fait, ce n'est pas une bonne idée (cela empêche l'utilisation d'index). Vous pouvez aussi utiliser UNION ALL. Ceci est probablement le meilleur moyen d'obtenir ce que vous voulez (en supposant que les tableaux ont des indices appropriés):

SELECT p.project_id 
FROM project p 
WHERE p.status = 'Active' 
UNION ALL 
SELECT i.project_id 
FROM invoice i 
WHERE invoice_date > '2016-01-01' AND 
     NOT EXISTS (SELECT 1 
        FROM project p2 
        WHERE p2.project_id = i.project_id AND p.status = 'Active' 
       ); 

Dans ce cas, vous pourriez avoir besoin select distinct dans le tableau invoice si un projet pourrait avoir plus d'un indice.

+0

Je vous ai entendu crier tout le chemin ici. – Hogan

+0

J'ai lu que les littéraux de date devraient être 'YYYYMMDD' dans SQL Server (pas de tirets), donc cela devrait être '20160101'. –

+0

@ThorstenKettner. . . YYYYMMDD est techniquement la meilleure forme pour les constantes de date dans SQL Server, car elle est sans ambiguïté quels que soient les paramètres d'internationalisation. Je préfère AAAA-MM-JJ parce que (1) il est (également) conforme à la norme ISO 8601; (2) je suis un être humain (malgré les rumeurs du contraire;) et il est plus facile à lire; (3) il est supporté par une grande variété de bases de données. –