J'ai 2 tables. Tableau A et B.

Le tableau A a un identifiant et des données qui ne sont pas importantes pour la question. La table B a un id et un A_id. Le dernier est utilisé pour combiner les 2 d'entre eux. Il peut y avoir plusieurs lignes avec le même A_id, seulement 1 ou pas du tout.

J'ai besoin d'une requête qui fera ce qui suit:

  1. Obtenez seulement 1 de chaque ligne du tableau A
  2. Joindre la table B dedans
  3. Aucun doublon du tableau A

Je sais que cela peut sembler compliqué, voici donc un exemple

Tableau A

id other info
 1 ...
 2 ...
 3 ...
 4 ...

Tableau B

id A_id
 1    2
 2    3
 3    3
 4    3

Production

 A.id other info B.id A_id
    1 ...        NULL  NULL
    2 ...           1     2   
    3 ...           2     3   
    4 ...        NULL  NULL

Donc, même s'il y a plusieurs lignes dans la table B dont A_id vaut 3, je n'ai besoin que de l'une d'entre elles. Et même s'il n'y a pas de ligne dans la table B dont le A_id vaut 1 ou 4, j'ai toujours besoin des deux pour apparaître.

C'est aussi clair que je peux éventuellement décrire ma question, veuillez donner des commentaires sur la façon dont je peux améliorer cette question.

0
FlorisdG 24 janv. 2017 à 19:51

4 réponses

Meilleure réponse

Un grand merci à Gordon Linoff de m'avoir poussé dans la bonne direction. La réponse initiale était:

select A.*,
       (select count(B.A_id) from B where B.A_id = A.id)
from A

Je suis désolé de ne pas l'avoir dit dans ma question, mais tout ce dont j'avais réellement besoin était d'obtenir chaque ligne de A et en même temps de vérifier s'il y avait une ligne dans le tableau B qui avait la même valeur dans A_id que A.id eu.

Cette requête compte toutes les lignes qui ont la même valeur de A_id que A.id.

Pour être clair, la sortie donnera:

 A.id other info count
    1 ...        0
    2 ...        1 
    3 ...        3  
    4 ...        0
0
FlorisdG 24 janv. 2017 à 17:59

Je ne peux pas le tester pour le moment mais il semble que vous vouliez quelque chose comme ça

SELECT * FROM A
LEFT JOIN B ON A.ID = B.A_ID

MISE À JOUR:

WITH tmp AS (
SELECT MIN(ID) ID FROM B GROUP BY A_id  
)
SELECT A.*, B.* FROM B
INNER JOIN tmp ON B.Id = tmp.ID
RIGHT JOIN A ON A.Id = B.A_Id
0
Kostis 24 janv. 2017 à 17:21

En supposant que votre base de données prend en charge ANSI SQL et lorsqu'il y a plusieurs lignes dans B, vous voulez la dernière basée sur l'ID:

with lastB (B_Id) as (
  select max(id) from tableB group by A_id 
),
BRows as (
select * from tableB 
    where Id in (select B_Id from lastB)
) 
select a.field1, a.field2, a.fieldN, 
   b.field1, b.field2, b.fieldN
from tableA a
left join BRows b on a.Id = b.A_Id 

EDIT: Oups. Vous avez édité votre question et avez répondu à la première. Ensuite, faites simplement max (), min ().

with lastB (B_Id) as (
  select min(id) from tableB group by A_id 
),
BRows as (
select * from tableB 
    where Id in (select B_Id from lastB)
) 
select a.field1, a.field2, a.fieldN, 
   b.field1, b.field2, b.fieldN
from tableA a
left join BRows b on a.Id = b.A_Id 

EDIT: Voici l'exemple MS SQL que j'ai promis:

DECLARE @tableA TABLE ( id INT, other VARCHAR(10) );
DECLARE @tableB TABLE
    (
      id INT ,
      A_Id INT ,
      other VARCHAR(10)
    );

INSERT  @tableA
        ( id, other )
VALUES  ( 1, 'v1' ),
        ( 2, 'v2' ),
        ( 3, 'v3' ),
        ( 4, 'v4' ); 

INSERT  @tableB
        ( id, A_Id, other )
VALUES  ( 1, 2, 'v21' ),
        ( 2, 3, 'v31' ),
        ( 3, 3, 'v32' ),
        ( 4, 3, 'v33' );

WITH    fromB ( B_Id )
          AS ( SELECT   MIN(id)
               FROM     @tableB
               GROUP BY A_Id
             ),
        BRows
          AS ( SELECT   *
               FROM     @tableB
               WHERE    id IN ( SELECT  B_Id
                                FROM    fromB )
             )
    SELECT  a.id AS A_Id ,
            a.other AS A_Other ,
            b.id AS B_Id ,
            b.other AS B_Other
    FROM    @tableA a
            LEFT JOIN BRows b ON a.id = b.A_Id; 

Résultat:

A_Id A_Other B_Id B_Other
1    v1      NULL NULL
2    v2      1    v21
3    v3      2    v31
4    v4      NULL NULL
0
Cetin Basoz 24 janv. 2017 à 17:24

Je pense que le moyen le plus simple est d'utiliser une sous-requête corrélée:

select a.*,
       (select max(b.id) from b where b.a_id = a.id)
from a;
1
Gordon Linoff 24 janv. 2017 à 16:54