2010-12-07 4 views
1

Je cherche à obtenir la première date avec la description du client et élément de la table exemple suivantObtenir premier enregistrement de deux tables

Pour créer mon exemple

CREATE TABLE cust 
(
CUSTNO int, 
ENAME varchar(50) 
) 

CREATE TABLE orders 
(
CUSTNO int, 
Description varchar(50), 
ORDERDATE date 
) 

INSERT INTO cust VALUES (7369, 'SMITH'); 
INSERT INTO cust VALUES (7499, 'ALLEN'); 
INSERT INTO cust VALUES (7521, 'WARD'); 
INSERT INTO cust VALUES (7566, 'JONES'); 
INSERT INTO cust VALUES (7654, 'MARTIN'); 
INSERT INTO cust VALUES (7698, 'BLAKE'); 
INSERT INTO cust VALUES (7782, 'CLARK'); 
INSERT INTO cust VALUES (7788, 'SCOTT'); 
INSERT INTO cust VALUES (7839, 'KING'); 
INSERT INTO cust VALUES (7844, 'TURNER'); 
INSERT INTO cust VALUES (7876, 'ADAMS'); 
INSERT INTO cust VALUES (7900, 'JAMES'); 
INSERT INTO cust VALUES (7902, 'FORD'); 
INSERT INTO cust VALUES (7934, 'MILLER'); 

INSERT INTO orders VALUES (7782, 'Something','17-DEC-1980'); 
INSERT INTO orders VALUES (7782, 'Something else', '17-DEC-2000'); 
INSERT INTO orders VALUES (7900, 'Something', '17-DEC-1980'); 
INSERT INTO orders VALUES (7900, 'Something else','17-DEC-1990'); 
INSERT INTO orders VALUES (7934, 'Something','17-DEC-1980'); 

tentais quelque chose comme ça

select [ENAME],[cust].[CUSTNO], MIN([ORDERDATE]),[Description] 
    from [cust],[orders] 
    where [cust].[CUSTNO]=[orders].[CUSTNO] 
    group by [cust].[CUSTNO],[ENAME],[Description] 

Mon problème est que cela renvoie trop de lignes. Je veux juste voir chaque client et ensuite lister sa première date (vide ou nul s'il n'y a pas de commande).

Des idées?

Répondre

2
SELECT c.[ENAME],c.[CUSTNO], o.[orderdate], o.[Description] 
    FROM cust c 
    LEFT JOIN orders o 
    ON c.custNo = o.custno 
    LEFT JOIN 
     (SELECT custno, min(orderdate) orderdate 
      FROM [orders] 
      GROUP BY custno) mo 
    ON mo.orderdate = o.orderdate 
     AND mo.custno = o.custno 

Vous avez besoin de la gauche se joint pour obtenir l'ordre si l'on existe, mais encore obtenir le client si aucune commande existe. La solution @conrad Frix fonctionnera également, mais j'ai inclus ceci dans le cas où vous utiliseriez une base de données qui n'accepte pas l'instruction with.

À l'avenir, vous devriez cesser d'écrire implict joint (en utilisant une virgule pour séparer les tables et de mettre les conditions de jointure inteh clause where). Ils sont une mauvaise technique de programmation et contribuent à expliquer pourquoi vous ne comprenez pas les jointures correctement (ou vous auriez pu utiliser une jointure à gauche).

+0

@HGLEM Je suppose que vous êtes fidèle à http://programmers.stackexchange.com/questions/610/what-syntax-element-do-you-love-most-in-a-programming-language-you-use -frequent/792 # 792 –

2
;with cteMinOrder as (
    select [CUSTNO], MIN([ORDERDATE]) as minDate 
     from [orders] 
     group by [CUSTNO] 
) 
select [ENAME],[cust].[CUSTNO], mo.minDate, [Description] 
    from [cust] 
     left join cteMinOrder mo 
      on [cust].[CUSTNO]=mo.[CUSTNO] 
     left join [orders] 
      on [cust].[CUSTNO]=[orders].[CUSTNO] 
       and mo.minDate = [orders].[ORDERDATE] 
-1

il suffit d'omettre [ENAME] et [Description] de la clause GROUP BY

+0

Cela produira une erreur. – bobs

3
with MinOrder as (
    select 
    custno, min(orderdate) orderdate 
    from [orders] 
    GROUP BY custno) 

    select [ENAME],[cust].[CUSTNO], o.[orderdate], [Description] 
    from 
    cust 
    LEFT JOIN orders o 
    ON cust.custNo = o.custno 
    LEFT JOiN MinOrder mo 
    ON mo.orderdate = o.orderdate 
    and mo.custno = o.custno 

Si vous ne pouvez pas utiliser un CTE, vous pouvez utiliser une vue en ligne à la place

select [ENAME],[cust].[CUSTNO], o.[orderdate], [Description] 
    from 
    cust 
    LEFT JOIN orders o 
    ON cust.custNo = o.custno 
    LEFT JOiN ( select 
    custno, min(orderdate) orderdate 
    from [orders] 
    GROUP BY custno) mo 
    ON mo.orderdate = o.orderdate 
    and mo.custno = o.custno 
1
select [ENAME],[cust].[CUSTNO],[minorderdate],[Description] 
from 
    [cust] 
left join 
    select [CUSTNO],MIN([ORDERDATE]) AS minorderdate 
    from [orders] 
    group by [CUSTNO] as t 
on [cust].[CUSTNO] = [t].[CUSTNO]; 

Syntaxe pourrait besoin de peaufiner en fonction du dialecte que vous utilisez, mais cette relation devrait faire ce que vous voulez fourmi.

Questions connexes