帮我改写这个查询

时间:2010-08-06 20:37:30

标签: sql mysql select

我有这个问题:

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结果......这应该返回超过100K。所以我在某处写错了?

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

6 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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")

答案 2 :(得分:1)

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

类似

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

答案 3 :(得分:0)

为什么不使用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')

答案 4 :(得分: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子句

中使用Case变量

答案 5 :(得分: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")

然后,它不是对分数进行硬编码,而是在表之间进行连接。我怀疑它会经常更新,但它会使以后更容易更改,并使整个代码维护和可读性更容易。