2010-01-15 6 views
2

J'ai deux tables:Créer une requête SQL pour récupérer des données à partir de deux tables

T_STOCK: clé primaire est id, seller, et quelques autres champs laissent dire a et b. T_FLOW: la clé primaire est (id + startdate) et quelques autres champs, par exemple c et d.

Je veux une requête qui retourne toutes les colonnes pour chaque enregistrements de T_STOCK concernant un seller spécifique, mais complété par les colonnes (startDate, c et d) de la table T_FLOW.

La relation entre T_STOCK et T_FLOW est basée sur l'attribut id. Chaque fois qu'un enregistrement avec un ID spécifique existe dans T_STOCK, au moins un enregistrement existe dans T_FLOW pour cet ID. Toutefois, il peut arriver que plusieurs enregistrements existent dans T_FLOW. Dans ce cas, je dois considérer seulement le le plus récent (c'est-à-dire celui avec max(startDate)).

En d'autres termes, si nous avons le contenu des tableaux suivants:

+---------------------+ 
|  T_STOCK  | 
+----+--------+---+---+ 
| ID | SELLER | a | b | 
+----+--------+---+---+ 
| 01 | foobar | 1 | 2 | 
+----+--------+---+---+ 
| 02 | foobar | 3 | 4 | 
+----+--------+---+---+ 
| 03 | foobar | 5 | 6 | 
+----+--------+---+---+ 

+---------------------------+ 
|   T_FLOW   | 
+----+------------+----+----+ 
| ID | StartDate | c | d | 
+----+------------+----+----+ 
| 01 | 01/01/2010 | 7 | 8 | 
+----+------------+----+----+ 
| 02 | 01/01/2010 | 9 | 10 | 
+----+------------+----+----+ 
| 02 | 07/01/2010 | 11 | 12 | 
+----+------------+----+----+ 
| 03 | 03/01/2010 | 13 | 14 | 
+----+------------+----+----+ 
| 03 | 05/01/2010 | 15 | 16 | 
+----+------------+----+----+ 

Le résultat de la requête doit être:

+----+--------+---+---+------------+----+----+ 
| ID | SELLER | a | b | startDate | c | d | 
+----+--------+---+---+------------+----+----+ 
| 01 | foobar | 1 | 2 | 01/01/2010 | 7 | 8 | 
+----+--------+---+---+------------+----+----+ 
| 02 | foobar | 3 | 4 | 03/01/2010 | 11 | 12 | 
+----+--------+---+---+------------+----+----+ 
| 03 | foobar | 5 | 6 | 01/01/2010 | 15 | 16 | 
+----+--------+---+---+------------+----+----+ 

Comment puis-je écrire ma requête alors?

+0

Votre relation me semble un peu bizarre. Votre stock 'PK' est' (id, vendeur) 'et vous pouvez avoir deux stocks avec le même' id', mais les flux sont liés par 'id' seulement. Est-ce intentionnel? – Quassnoi

+1

+1 pour votre art ascii! –

+0

@Quassnoi, oui, c'est intentionnel :) – romaintaz

Répondre

3
SELECT * 
FROM t_stock s 
JOIN (
     SELECT f.*, ROW_NUMBER() OVER (PARTITION BY id ORDER BY startDate DESC) AS rn 
     FROM t_flow f 
     ) f 
ON  f.id = s.id 
     AND f.rn = 1 

est ici une solution qui n'utilise pas les fonctions analytiques:

SELECT * 
FROM t_stock s 
JOIN t_flow f 
ON  (f.id, f.startDate) = 
     (
     SELECT id, MAX(startDate) 
     FROM t_flow fi 
     WHERE fi.id = s.id 
     GROUP BY 
       id 
     ) 
+0

Y at-il une solution pour écrire cette requête sans utiliser 'row_number() over (partition ...'? – romaintaz

0
SELECT DISTINCT 
     s.* 
     ,FIRST_VALUE(f.startdate) 
     OVER (PARTITION BY f.id ORDER BY f.startdate DESC) startdate 
     ,FIRST_VALUE(f.c) 
     OVER (PARTITION BY f.id ORDER BY f.startdate DESC) c 
     ,FIRST_VALUE(f.d) 
     OVER (PARTITION BY f.id ORDER BY f.startdate DESC) d 
FROM t_stock s, t_flow f 
WHERE f.id = s.id 
1

Vous obtenez le plus récent record T_FLOW utilisant l'analyse, as shown by Quassnoi, ou à l'aide:

select id, max(startdate) last_start_date from t_flow group by id; 

Vous pouvez ensuite joindre ceci avec votre table T_STOCK - quelque chose comme:

select 
    s.*, 
    f.* 
from 
    t_stock s 
     inner join t_flow f on 
       f.id = s.id 
      and (f.id, f.startdate) in 
       (
       select 
        id, 
        max(startdate) laststartdate 
       from 
        t_flow 
       group by 
        id 
       ) 
+0

Vous avez besoin d'une autre jointure pour obtenir les autres colonnes de 't_flow'. – Quassnoi

+0

Je comme mid-edit :) - et ne fonctionne toujours pas –

+0

Cela devrait être '(f.id, f.startdate) IN ...' – Quassnoi

0
select id, max(startdate) last_start_date from t_flow group by id; 

Ensuite, vous pouvez rejoindre avec votre table de T_STOCK, quelque chose comme ceci:

select s.*, f.* from t_stock s inner join t_flow f on f.id = s.id 
and (f.id, f.startdate) in (select id, max(startdate) laststartdate 
       from t_flow group by id) 
Questions connexes