J'essaie de joindre deux tables à l'aide d'une jointure gauche. Et le jeu de résultats ne doit inclure que le premier enregistrement de la table jointe "droite".
Disons que j'ai deux tableaux A et B comme ci-dessous;
Tableau "A"
code | emp_no
101 | 12222
102 | 23333
103 | 34444
104 | 45555
105 | 56666
Tableau "B"
code | city | county
101 | Glen Oaks | Queens
101 | Astoria | Queens
101 | Flushing | Queens
102 | Ridgewood | Brooklyn
103 | Bayside | New York
Sortie attendue:
code | emp_no | city | county
101 | 12222 | Glen Oaks | Queens
102 | 23333 | Ridgewood | Brooklyn
103 | 34444 | Bayside | New York
104 | 45555 | NULL | NULL
105 | 56666 | NULL | NULL
Si vous remarquez que mon résultat n'a que le seul enregistrement correspondant de la table "B" (peu importe quel enregistrement correspond) après la jointure gauche (et il s'agit d'un mappage un à plusieurs)
Je dois choisir le premier enregistrement correspondant dans le tableau B et ignorer toutes les autres lignes.
Veuillez aider!
Merci
Après avoir joué un peu, cela s'avère plus compliqué que ce à quoi je m'attendais! En admettant que table_b
a une seule colonne unique (disons, une clé primaire à un seul champ), il semble que vous pouvez faire ceci:
SELECT table_a.code,
table_a.emp_no,
table_b.city,
table_b.county
FROM table_a
LEFT
JOIN table_b
ON table_b.code = table_a.code
AND table_b.field_that_is_unique =
( SELECT TOP 1
field_that_is_unique
FROM table_b
WHERE table_b.code = table_a.code
)
;
OUTER APPLY
Si pris en charge par la base de données, OUTER APPLY
est une option efficace et concise.
SELECT *
FROM
Table_A a
OUTER APPLY
(SELECT TOP 1 *
FROM Table_B b_1
WHERE b_1.code = a.code
) b
;
Il en résulte une jointure gauche au indéterminé premier enregistrement correspondant. Mes tests montrent qu'il est plus rapide que toute autre solution publiée (sur MS SQL Server 2012).
La réponse la plus votée ne me semble pas correcte et semble trop compliquée. Il vous suffit de regrouper par le champ de code du tableau B dans votre sous-requête et de sélectionner l'ID maximum par regroupement.
SELECT
table_a.code,
table_a.emp_no,
table_b.city,
table_b.county
FROM
table_a
LEFT JOIN
table_b
ON table_b.code = table_a.code
AND table_b.field_that_is_unique IN
(SELECT MAX(field_that_is_unique)
FROM table_b
GROUP BY table_b.code)
Si vous utilisez SQL Server 2005 ou une version ultérieure, vous pouvez utiliser ranking pour obtenir ce que vous voulez. En particulier, ROW_NUMBER()
semble bien correspondre à vos besoins:
WITH B_ranked AS (
SELECT
*,
rnk = ROW_NUMBER() OVER (PARTITION BY code ORDER BY city)
FROM B
)
SELECT
A.code,
A.emp_no,
B.city,
B.county
FROM A
LEFT JOIN B_ranked AS B ON A.code = B.code AND b.rnk = 1
OR
WITH B_unique_code AS (
select * from(
SELECT
*,
rnk = ROW_NUMBER() OVER (PARTITION BY code ORDER BY city)
FROM B
) AS s
where rnk = 1
)
SELECT
A.code,
A.emp_no,
B.city,
B.county
FROM A
LEFT JOIN B_unique_code AS B ON A.code = B.code
J'ai modifié la réponse de ruakh et cela semble fonctionner parfaitement avec mysql.
SELECT
table_a.code,
table_a.emp_no,
table_b.city,
table_b.county
FROM table_a a
LEFT JOIN table_b b
ON b.code = a.code
AND b.id = ( SELECT id FROM table_b
WHERE table_b.code = table_a.code
LIMIT 1
)
;
Dans Oracle, vous pouvez faire:
WITH first_b AS (SELECT code, min(rowid) AS rid FROM b GROUP BY code))
SELECT a.code, a.emp_no, b.city, b.county
FROM a
INNER JOIN first_b
ON first_b.code = a.code
INNER JOIN b
ON b.rowid = first_b.rid
c'est ainsi:
Select * From TableA a
Left Join TableB b
On b.Code = a.Code
And [Here put criteria predicate that 'defines' what the first record is]
Hé, si la ville et le comté sont uniques, alors utilisez-les
Select * From TableA a
Left Join TableB b
On b.Code = a.Code
And b.City + b.county =
(Select Min(city + county)
From TableB
Where Code = b.Code)
Mais le fait est que vous devez y mettre une expression pour dire au processeur de requêtes ce que signifie être premier.