2017-10-18 1 views
0

Ayant cette 2 tablescomment gauche Inscrivez-vous avec des résultats Table2 à NULL, puis Tableau2 résultats avec le drapeau

CREATE TABLE Table1 (
    Table1_Key INT IDENTITY(1,1), 
    Info NVARCHAR(50), 
    PRIMARY KEY (Table1_Key) 
); 


CREATE TABLE Table2 (
    Table2_Key INT IDENTITY(1,1), 
    Info_table2 NVARCHAR(50), 
    Table1_FKey INT, 
    Flag BIT NOT NULL, 
    PRIMARY KEY (Table2_Key,Table1_FKey), 
    FOREIGN KEY (Table1_FKey) REFERENCES Table1(Table1_Key) 
); 

avec des valeurs comme ce

INSERT INTO Table1 
VALUES ('Record 1'), ('Record 2'), ('Record 3') 

INSERT INTO Table2 
VALUES ('test 1',1,1), ('test 2',1,0), ('test 3',1,1), 
     ('test 1',2,0), ('test 2',2,1), ('test 3',2,2) 

Il est possible de faire une LEFT JOIN avec Table2 que sélectionner tout Table1 avec des valeurs NULL sur Table2AND les valeurs Table2 avec le Flag dans 1?

Résultat attendu:

Table1_Key Info Table2_Key Info_table2 Table1_FKey Flag 
------------------------------------------------------------------ 
    1   Record 1  NULL  NULL  NULL  NULL 
    2   Record 2  NULL  NULL  NULL  NULL 
    3   Record 3  NULL  NULL  NULL  NULL 
    1   Record 1  1   test 1  1  1 
    1   Record 1  3   test 3  1  1 
    2   Record 2  5   test 2  2  1 
    2   Record 2  6   test 3  2  1 

la jointure, je suis en train de faire ce qui ne fonctionne pas:

SELECT * FROM Table1 
LEFT JOIN Table2 
ON Table1_FKey = Table1_Key 
WHERE Flag = 1 
+1

Changez 'WHERE' en' AND' pour obtenir le comportement true 'left join' – HoneyBadger

+0

ou utilisez la jointure interne –

+0

Il s'agit d'un problème d'ordre de fonctionnement. La jointure se produit en créant des enregistrements NULL. Ensuite, vous les excluez en disant flag = 1. Pour les conserver, déplacez la limite à la jointure afin que la limite soit appliquée dans le cadre de la jointure et que les enregistrements NULL soient conservés. 'LEFT JOIN table2 sur Table1_FKEY = Table1_key AND flag = 1' – xQbert

Répondre

1

DEMO:

déclarations de cas sur le drapeau devraient le faire. pour chacune des colonnes de la table 2 devrait le faire.

SELECT table1_key 
    , info 
    , case when flag =0 then null else table2_key end as table2_key 
    , case when flag =0 then null else info_table2 end as info_table2 
    , case when flag =0 then null else table1_fkey end as table1_fkey 
    , case when flag =0 then null else flag end as flag 
FROM Table1 
LEFT JOIN Table2 
    ON Table1_FKey = Table1_Key 
ORDER BY table2_key 

nous donner:

+------------+----------+------------+-------------+-------------+--------+ 
| table1_key | info | table2_key | info_table2 | table1_fkey | flag | 
+------------+----------+------------+-------------+-------------+--------+ 
|   1 | Record 1 | (null)  | (null)  | (null)  | (null) | 
|   2 | Record 2 | (null)  | (null)  | (null)  | (null) | 
|   3 | Record 3 | (null)  | (null)  | (null)  | (null) | 
|   1 | Record 1 | 1   | test 1  | 1   | true | 
|   1 | Record 1 | 3   | test 3  | 1   | true | 
|   2 | Record 2 | 5   | test 2  | 2   | true | 
|   2 | Record 2 | 6   | test 3  | 2   | true | 
+------------+----------+------------+-------------+-------------+--------+ 
+1

Donc, pas de filtre et d'instructions de cas d'utilisation, donc aucun enregistrement n'est réellement supprimé; juste annulé si le drapeau n'est pas nul. et sans syndicat – xQbert

+0

@xQbert Maintenant, ce serait plus utile pour moi. Merci, j'ai trouvé difficile de le résoudre sans 'union' – Ragmar

2

Donc, fondamentalement, cela? :

SELECT * FROM Table1 
INNER JOIN Table2 
ON Table1_FKey = Table1_Key 
WHERE Flag = 1 
UNION ALL 
SELECT t1.*,NULL,NULL,NULL,NULL FROM Table1 t1 
+0

Cela me donne le prévu résultat, mais cherchait un moyen de le faire sans 'UNION' – Ragmar

+2

Eh bien, c'est un problème .. Un enregistrement peut soit trouver une correspondance, ou non. Il ne peut pas faire les deux (Vous voulez pour chaque enregistrement dans la table1, une ligne avec 'NULL' et une ligne/s avec la/les correspondances). Ce n'est pas possible pour autant que je sache. @Ragmar – sagi

1

Cocher cette requête:

  1. valeurs sélectionnées dans le tableau 1
  2. Union tous
  3. Fetch Les valeurs fondées sur la condition et à gauche rejoindre

    SELECT  Table1_Key, Info, NULL AS Expr3, NULL AS Expr4, NULL AS Expr5, NULL AS Expr6 
    FROM   Table1 
    
    UNION ALL 
    
    SELECT  Table1_1.Table1_Key, Table1_1.Info, Table2.Table2_Key, Table2.Info_table2, Table2.Table1_FKey, Table2.Flag 
    FROM   Table2 LEFT JOIN 
           Table1 AS Table1_1 ON Table2.Table1_FKey = Table1_1.Table1_Key 
    WHERE  (Table2.Flag = 1) 
    

Sortie:

enter image description here

+0

C'est fondamentalement le même que @sagi, mais comme je lui ai dit, je l'aurais aimé sans 'UNION' – Ragmar

2

Votre résultat attendu est impossible sans une UNION additionnelle ajoutée comme décrit par Sagi.

En spécifiant la condition LEFT JOIN comme Table1_Key = Table1_Fkey, vous définissez le jeu de résultats à inclure les lignes de table1 où la condition ne match (fiche 1 et fiche 2), et les lignes où la condition ne match (record 3). Pensez-y de cette façon ...si vous croisez-vous joindre aux tables (correspondre tous les records dans le tableau 1 avec chaque enregistrement table2), vous vous retrouvez avec ceci:

Table1_Key Info Table2_Key Info_table2 Table1_FKey Flag 
------------------------------------------------------------------ 
1   Record 1  1   test 1  1   1 
1   Record 1  2   test 2  1   0 
1   Record 1  3   test 3  1   1 
1   Record 1  4   test 1  2   0 
1   Record 1  5   test 2  2   1 
1   Record 1  6   test 3  2   1   
2   Record 2  1   test 1  1   1 
2   Record 2  2   test 2  1   0 
2   Record 2  3   test 3  1   1 
2   Record 2  4   test 1  2   0 
2   Record 2  5   test 2  2   1 
2   Record 2  6   test 3  2   1   
3   Record 3  1   test 1  1   1 
3   Record 3  2   test 2  1   0 
3   Record 3  3   test 3  1   1 
3   Record 3  4   test 1  2   0 
3   Record 3  5   test 2  2   1 
3   Record 3  6   test 3  2   1   

Cependant, en spécifiant votre condition de jointure comme Table1_Key = Table1_Fkey AND Flag = 1, vous restreindre le jeu de résultats à ces lignes où cette condition est remplie:

Table1_Key Info Table2_Key Info_table2 Table1_FKey Flag 
------------------------------------------------------------------ 
1   Record 1  1   test 1  1   1 
1   Record 1  3   test 3  1   1 
2   Record 2  5   test 2  2   1 
2   Record 2  6   test 3  2   1   

Et parce qu'il est un LEFT JOIN, tous les enregistrements de table1 qui n'a pas trouvé un match sur Tableau2 sera inclus:

Table1_Key Info Table2_Key Info_table2 Table1_FKey Flag 
------------------------------------------------------------------ 
1   Record 1  1   test 1  1   1 
1   Record 1  3   test 3  1   1 
2   Record 2  5   test 2  2   1 
2   Record 2  6   test 3  2   1   
3   Record 3  NULL  NULL  NULL  NULL  

Ainsi, afin d'obtenir le jeu de résultats que vous recherchez, vous devez explicitement UNION sur les lignes supplémentaires de Tableau 1:

SELECT * 
FROM Table1 
LEFT JOIN Table2 
ON Table1_FKey = Table1_Key AND Flag = 1 
UNION ALL 
SELECT t1.*,NULL,NULL,NULL,NULL FROM Table1 t1 
WHERE t1.Table1_Key in (1,2) 

... pour obtenir le résultat souhaité:

Table1_Key Info Table2_Key Info_table2 Table1_FKey Flag 
------------------------------------------------------------------ 
1   Record 1  1   test 1  1   1 
1   Record 1  3   test 3  1   1 
2   Record 2  5   test 2  2   1 
2   Record 2  6   test 3  2   1   
3   Record 3  NULL  NULL  NULL  NULL  
1   Record 1  NULL  NULL  NULL  NULL  
2   Record 2  NULL  NULL  NULL  NULL  
+1

insn't table2_key le résultat attendu incorrect? tous les 1? quand l'ensemble devrait être {NULL, NULL, NULL, 1,3,5,6} – xQbert

+0

@TruAvatar votre réponse était vraiment bonne, mais @xQbert posté maintenant une solution sans 'Union'. Vous m'aidez à comprendre un peu plus de SQL. Merci – Ragmar

+1

Cette méthode 'CASE' crache le résultat que vous recherchez dans cet exemple, mais soyez prudent lorsque vous travaillez avec des données réelles. Si vous avez deux lignes dans Table2 avec Table1_Fkey = 1 et Flag = 0, vous obtiendrez des lignes dupliquées de {1, Record 1, NULL, NULL, NULL, NULL}. Ce n'est peut-être pas un problème pour ce que vous faites, mais soyez conscient. – TruAvatar