2010-08-06 3 views
1

Je cette requête:Aidez-moi à réécrire cette requête

SELECT diamond_id, carat, clarity, color, cut, 
    CASE clarity 
     WHEN "FL" THEN 0 
     WHEN "IF" THEN 1 
     WHEN "VVS1" THEN 2 
     WHEN "VVS2" THEN 3 
     WHEN "VS1" THEN 4 
     WHEN "VS2" THEN 5 
     WHEN "SI1" THEN 6 
     WHEN "SI2" THEN 7 
     WHEN "I1" THEN 8 
     WHEN "I2" THEN 9 
     WHEN "I3" THEN 10 
     ELSE -1 
    END AS clarity_score, 
    CASE cut 
     WHEN "ideal" THEN 0 
     WHEN "excellent" THEN 1 
     WHEN "very good" THEN 2 
     WHEN "good" THEN 3 
     WHEN "fair" THEN 4 
     WHEN "poor" THEN 5 
     ELSE -1 
    END AS cut_score  
    FROM rapnet_diamonds 
WHERE 
    shape IN ("round","princess","oval") 
AND (carat BETWEEN ".1" AND "5") 
AND (color BETWEEN "D" AND "Z") 
AND (clarity_score BETWEEN "0" AND "10") 
AND (cut_score BETWEEN "0" AND "5") 

Comme vous pouvez le voir, je produis les clarity_score et cut_score colonnes à la volée afin que je puisse les utiliser dans ma clause WHERE. Tout d'abord, cela me donne une erreur en me disant que clarity_score n'existe pas. Donc je pensais que c'est peut-être un de ces cas où je dois utiliser HAVING à la place?

donc je changé ma clause where:

WHERE 
    shape IN ("round","princess","oval") 
AND (carat BETWEEN ".1" AND "5") 
AND (color BETWEEN "D" AND "Z") 
HAVING 
    (clarity_score BETWEEN "0" AND "10") 
AND (cut_score BETWEEN "0" AND "5") 

Je suis pas d'erreur, mais 0 ... Cela devrait être au-dessus de 100K retournaient. Donc j'ai écrit quelque chose de mal quelque part?

AVANT de COMMENCER cela, cependant, je NE veux PAS CHOISIR ces 2 champs générés, est-ce que je peux l'écrire afin que je ne récupère pas ces 2 champs, juste en les utilisant dans la clause where?

Répondre

5

Vous pouvez effectuer les opérations suivantes.

Créer deux tables de consultation

create table clarity_lookup 
    (clarity_score int, 
    clarity char(5)) 

create table cut_lookup 
    (cut_score int, 
    cut char(10)) 

charge les tables de consultation avec les données

INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (0, 'FL') 
INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (1, 'IF') 
INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (2, 'VVS1') 
INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (3, 'VVS2') 
INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (4, 'VS1') 
INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (5, 'VS2') 
INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (6, 'SI1') 
INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (7, 'SI2') 
INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (8, 'I1') 
INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (9, 'I2') 
INSERT INTO clarity_lookup (clarity_score, clarity) VALUES (10, 'I3') 

INSERT INTO cut_lookup (cut_score, cut) VALUES (0, 'ideal') 
INSERT INTO cut_lookup (cut_score, cut) VALUES (1, 'excellent') 
INSERT INTO cut_lookup (cut_score, cut) VALUES (2, 'very good') 
INSERT INTO cut_lookup (cut_score, cut) VALUES (3, 'good') 
INSERT INTO cut_lookup (cut_score, cut) VALUES (4, 'fair') 
INSERT INTO cut_lookup (cut_score, cut) VALUES (5, 'poor') 

Votre requête ressemblerait à ce qui suit. En résumé, vous joindrez vos nouvelles tables, qui représentent les données dans vos clauses CASE d'origine, à la table de diamants basée sur les scores, mais afficher les descriptions dans votre clause SELECT.

SELECT rapnet_diamonds.diamond_id, rapnet_diamonds.carat, 
    clarity_lookup.clarity, rapnet_diamonds.color, cut_lookup.cut 
FROM rapnet_diamonds 
LEFT OUTER JOIN clarity_lookup ON rapnet_diamonds.clarity_score = clarity_lookup.clarity_score 
LEFT OUTER JOIN cut_lookup ON rapnet_diamonds.cut_score = cut_lookup.cut_score 
WHERE rapnet_diamonds.shape IN ('round','princess','oval') 
    AND (rapnet_diamonds.carat BETWEEN .1 AND 5) 
    AND (rapnet_diamonds.color BETWEEN 'D' AND 'Z') 
    AND (rapnet_diamonds.clarity_score BETWEEN 0 AND 10) 
    AND (rapnet_diamonds.cut_score BETWEEN 0 AND 5) 
+0

+1: Pourrait utiliser la table de temp si l'information n'est pas nécessaire ailleurs. La seule modification que je ferais serait d'utiliser 'COALESCE (clarity_lookup.clarity_score, -1)', etc. –

2

Cela ne fonctionne-t-il pas? (J'ai une expérience limitée avec MySQL.)

SELECT diamond_id, carat, clarity, color, cut 
    FROM rapnet_diamonds 
WHERE 
    shape IN ("round","princess","oval") 
AND (carat BETWEEN ".1" AND "5") 
AND (color BETWEEN "D" AND "Z") 
AND ( CASE clarity 
     WHEN "FL" THEN 0 
     WHEN "IF" THEN 1 
     WHEN "VVS1" THEN 2 
     WHEN "VVS2" THEN 3 
     WHEN "VS1" THEN 4 
     WHEN "VS2" THEN 5 
     WHEN "SI1" THEN 6 
     WHEN "SI2" THEN 7 
     WHEN "I1" THEN 8 
     WHEN "I2" THEN 9 
     WHEN "I3" THEN 10 
     ELSE -1 
    END BETWEEN "0" AND "10") 
AND ( CASE cut 
     WHEN "ideal" THEN 0 
     WHEN "excellent" THEN 1 
     WHEN "very good" THEN 2 
     WHEN "good" THEN 3 
     WHEN "fair" THEN 4 
     WHEN "poor" THEN 5 
     ELSE -1 
    END BETWEEN "0" AND "5") 
+0

Oui cela fonctionne! Merci! –

1

je mettrais la logique de déclaration de cas dans une table de décodeur, et joindre à cela. Ensuite, vous pouvez utiliser les colonnes de la clause where, et cela simplifie le SQL.

quelque chose comme

create table ClarityCode 
(
    Clarity char(x) not null 
, CodeID int not null 
) 
+0

Pouvez-vous élaborer à ce sujet? ou pointez sur un tutoriel. –

+0

Je pense que Bobs répond à peu près l'explique. Ce que j'aurais fait si je n'avais pas été pressé de quitter mon travail un vendredi. – Rawheiser

0

pourquoi ne pas utiliser IN?

SELECT diamond_id, carat, clarity, color, cut 
FROM rapnet_diamonds 
WHERE 
shape IN ("round","princess","oval") AND 
(carat BETWEEN ".1" AND "5") AND 
(color BETWEEN "D" AND "Z") AND 
clarity IN ('FL', 'IF', 'VVS1', 'VVS2', 'VS1', 'VS2', 'SI1', 'SI2', 'I1', 'I2', 'I3') AND 
cut IN ('ideal', 'excellent', 'very good', 'good', 'fair', 'poor') 
+0

Cela ne me permettra pas de faire quelque chose comme BETWEEN "juste" ET "excellent" –

0

je prendrais votre requête et modifier vous codez peu pour le faire fonctionner

SELECT * FROM 
    (
    SELECT diamond_id, carat, clarity, color, cut, 
     CASE clarity 
      WHEN "FL" THEN 0 
      WHEN "IF" THEN 1 
      WHEN "VVS1" THEN 2 
      WHEN "VVS2" THEN 3 
      WHEN "VS1" THEN 4 
      WHEN "VS2" THEN 5 
      WHEN "SI1" THEN 6 
      WHEN "SI2" THEN 7 
      WHEN "I1" THEN 8 
      WHEN "I2" THEN 9 
      WHEN "I3" THEN 10 
      ELSE -1 
     END AS clarity_score, 
     CASE cut 
      WHEN "ideal" THEN 0 
      WHEN "excellent" THEN 1 
      WHEN "very good" THEN 2 
      WHEN "good" THEN 3 
      WHEN "fair" THEN 4 
      WHEN "poor" THEN 5 
      ELSE -1 
     END AS cut_score  
     FROM rapnet_diamonds 
    WHERE 
     shape IN ("round","princess","oval") 
    AND (carat BETWEEN ".1" AND "5") 
    AND (color BETWEEN "D" AND "Z") 
)t 
WHERE 
    (clarity_score BETWEEN "0" AND "10") 
    AND (cut_score BETWEEN "0" AND "5") 

Vous ne pouvez pas utiliser des variables de cas dans la clause WHERE

0

En réponse au désir de plus d'explications pour l'idée de table divisée:

Plutôt que d'avoir tout dans une instruction CASE, vous stockez les informations de clarté dans un second tableau. Il pourrait ressembler à ceci:

Clarity_Table 
----------------------- 
Clarity_score | clarity 
----------------------- 
0    | FL 
1    | IF 
2    | VVS1 
3    | VVS2 
4    | VS1 
5    | VS2 
... 
10   | I3 

Et la même chose pour Cut_Table, nous espérons que vous avez l'idée d'en haut.

puis, changer votre requête:

SELECT diamond_id, carat, clarity, color, cut, clarity_score, cut_score  
    FROM rapnet_diamonds JOIN clarity_table USING(clarity) 
         JOIN cut_table USING(cut) 
WHERE 
    shape IN ("round","princess","oval") 
AND (carat BETWEEN ".1" AND "5") 
AND (color BETWEEN "D" AND "Z") 
AND (clarity_score BETWEEN "0" AND "10") 
AND (cut_score BETWEEN "0" AND "5") 

Alors, plutôt que de coder en dur les scores, il ne une jointure entre les tables. Je doute qu'il sera mis à jour très souvent, mais cela rendrait plus facile le changement ultérieur des choses, et faciliterait grandement la lisibilité de la maintenance du code &.

Questions connexes