2010-11-14 4 views
2

J'ai les tableaux suivants:requête SQL Inverted

{Tableau 1 ArticleNo (int), ArtDescription (string)}

{Tableau2 ArticleNo (int), Année (date)}

Table1.ArticleNo est une clé primaire. Table2.ArticleNo est une clé étrangère fait référence à table1.ArticleNo

Il est difficile d'expliquer ce que je veux interroger, alors voici un court exemple:


Tableau 1

(1,Desk) 
(2,Chair) 
(3,Ruler) 

Tableau2

(1,2000) 
(1,2000) 
(2,2001) 

La requête doit retourner:

1 Desk 2001 
2 Chair 2000 
3 Ruler 2000 
3 Ruler 2001 

Tous les articles qui ne sont pas vendus (ou autre) dans toutes les années (toutes les années de table2). J'espère que vous comprenez mon exemple - la requête semble être très complexe.


Voici mon approche à une solution:

SELECT table1.ArticleNo,table1.ArtDescription,table2.Year 
FROM table1 
JOIN table2 
ON table1.ArticleNo=table2.ArticleNo 
WHERE NOT table1.ArticleNo IN (SELECT table2.Year FROM table2); 

J'ai essayé beaucoup de choses différentes .. J'espère que vous pouvez m'aider!

+1

Je pense que vous voudrez peut-être repenser vos schémas de table. Cela va devenir très complexe très rapidement et ne procure aucun avantage immédiat. Peut-être votre deuxième table devrait être les années dans lesquelles les articles sont vendus, par opposition à ne pas être vendus. –

+0

Dans votre exemple sur la ligne "WHERE NOT table1.ArticleNo IN (SELECT table2.Year FROM table2);" vous comparez ArticleNo à un an. De votre exemple de données qui ne correspondra jamais. –

+0

Quel moteur de base de données utilisez-vous? – Quassnoi

Répondre

2
SELECT t1.*, t2.year 
FROM t1 
CROSS JOIN 
     (
     SELECT DISTINCT year 
     FROM t2 
     ) t2 
WHERE (t1.id, t2.year) NOT IN 
     (
     SELECT t2.id, t2.year 
     FROM t2 
     ) 

Créer un index sur t2 (year, id) (dans cet ordre) pour la requête de travailler rapidement.

+0

Merci pour votre aide! Et désolé de la mauvaise mise en forme - maintenant je sais comment faire mieux. –

0

Il y a plusieurs façons de le faire. Deux exemples:

select 
    t1.ArtDescription, 
    y.Year 
from 
    Table1 t1 
    join (
    select distinct 
     t2.Year 
    from 
     Table2 t2 
) y on 1=1 
where 
    not exists (
    select 
     1 
    from 
     Table2 tx2 
    where 
     tx2.ArticleNo = t1.ArticleNo and tx2.Year = y.Year) 

Oracle (SQL Server peut faire la même chose, utiliser EXCEPT au lieu de MINUS):

select 
    t1.ArtDescription, 
    y.Year 
from 
    Table1 t1 
    join (
    select distinct 
     t2.Year 
    from 
     Table2 t2 
) y on 1=1 
MINUS 
select 
    t12.ArtDescription 
    t22.Year 
from 
    Table1 t12 
    join Table2 t22 on t12.ArticleNo = t22.ArticleNo 
+0

Nice, je pense que vous pouvez l'écrire un peu plus clairement en remplaçant le "' joint ...sur 1 = 1' "avec un" jointure croisée "" – Andomar

+0

ahh .. le premier n'a pas l'air si complexe Merci! –

1

Vous pouvez utiliser un cross join pour créer une liste de toutes les combinaisons d'objets + année. Ensuite, vous pouvez filtrer les lignes sans vente avec une condition not exists:

select * 
from t1 items1 
cross join  
     (
     select distinct year 
     from t2 sales1 
     ) sales2 
where not exists 
     (
     select * 
     from t2 sales3 
     where sales3.ItemId = items1.ItemId 
       and sales3.Year = sales2.Year 
     ) 
0
SELECT DISTINCT table1.ArticleNo,table1.ArtDescription,table2.Year 
    FROM table1 CROSS JOIN table2 
    WHERE table1.ArticleNo != table2.ArticleNo order by table1.ArticleNo;