2010-08-06 112 views
1

我有这个疑问:帮我重写此查询

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") 

正如你可以看到我动态生成的clarity_scorecut_score列,所以我可以在我的WHERE子句中使用它们。

首先,这给我一个错误,告诉我clarity_score不存在。所以我想也许这是我需要使用HAVING的情况之一?

,所以我改变了我的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") 

我没有错误,但结果0 ...这应该返回超过10万。所以我在某处写了这个错误?

在开始重写这个之前,我不想选择这两个生成的字段,有没有办法可以写出来,所以我没有检索这两个字段,只是在where子句中使用它们?

回答

5

您可以执行以下操作。

创建两个查表

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

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

加载数据

查找表
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') 

你的查询将如下所示。总之,您可以根据分数将您的新表(表示原始CASE子句中的数据)加入钻石表中,但在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:如果信息在其他地方不需要,可以使用临时表。我只会改变使用'COALESCE(clarity_lookup.clarity_score,-1)',等等 – 2010-08-07 01:06:24

2

这不工作? (我对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

是的,这是工作!谢谢! – 2010-08-06 20:44:54

1

我会把case语句逻辑放到查找解码器表中,然后加入到这个表中。 然后,您可以使用where子句中的列,并简化了SQL。

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

你能详细解释一下吗?或指向一个教程。 – 2010-08-06 20:57:16

+0

我认为鲍勃斯的回答很好解释它。如果我没有急于在周五离开工作,我会做什么。 – Rawheiser 2010-08-07 02:35:29

0

,为什么不用呢?

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

这不会让我做一些事情,如“公平”和“优秀” – 2010-08-06 20:55:50

0

我把你的查询和修改你的代码点点得到它的工作

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") 

在不能使用情况的变量where子句

0

为响应渴望更多的解释拆分表思路:

而不是在CASE语句中包含所有内容,您将清晰度信息存储在第二个表中。它可能是这个样子:

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

而且同样的事情Cut_Table,希望你从上面的想法。

然后,改变你的查询:

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") 

然后,而不是硬编码的成绩,但它一表之间的连接。我怀疑它会经常更新,但它会使事情变得更容易,并且使整体代码维护更加容易。