SELECT .. FROM(SELECT .. FROM ..)。如何改进此查询?

时间:2014-10-08 14:05:47

标签: sql sqlite

我正在学习SQL并且一直在浏览GalaXQL应用程序的章节。

我已经在回答问题时编写了以下问题" Hilight星系(或星星),它们具有银河系中轨道距离最远的行星。记得在开始之前清除旧的hilights。"

此查询返回结果starid:23334,当插入到hilight表中时,允许我前进。但是,在将这个结果交还给我之前,程序会挂起很长很长时间,所以我怀疑从数据库中提取这些信息的效率要高得多。

此查询有效,但需要很长时间才能处理,如何改进此查询?

INSERT INTO hilight 
SELECT DISTINCT s.starid 
FROM planets AS p, stars AS s, moons AS m 
WHERE s.starid=(SELECT starid 
                FROM planets 
                WHERE orbitdistance=(SELECT MAX(orbitdistance) 
                                     FROM planets));

我在此查询结构背后的逻辑

首先找到离桌子最远的轨道距离的行星"行星"。

第二比较"最高轨道距离"到了" orbitdistance"桌子的领域"行星"并返回" starid"与该领域有关。

第三次比较字段的值" starid"在表格"行星"到现场" starid"在表格"明星"然后插入" starid"到桌子" hilight"。

数据结构:

enter image description here

3 个答案:

答案 0 :(得分:7)

好吧,让我们先查看您的基本查询。我知道你已经有一个有效的答案,但我觉得我需要向你解释你的查询中发生了什么。

INSERT INTO hilight 
SELECT DISTINCT 
    s.starid 
FROM planets AS p, stars AS s, moons AS m 
WHERE s.starid=(
    SELECT 
        starid 
    FROM planets 
    WHERE orbitdistance=(
            SELECT 
                MAX(orbitdistance) 
            FROM planets
            )
        );

所以在你的FROM子句中,你也使用了几种旧式连接。您还缺少ON子句。这被称为CROSS JOIN,它将产生我们称之为笛卡儿积的产品。结果集将第一个表中的行数乘以第二个表中的行数,依此类推。依次类推。

因此,我们可以通过简单地修复连接语法并加入您在图表中显示的关系来解决这个问题。

INSERT INTO hilight 
SELECT --DISTINCT probably no longer needed as we aren't artifficially creating duplicate rows
    s.starid 
FROM planets AS p
inner join stars AS s
    on s.StarID = p.starid 
inner join moons AS m 
    m.planetID = p.planetID
WHERE s.starid=(
    SELECT 
        starid 
    FROM planets 
    WHERE orbitdistance=(
            SELECT 
                MAX(orbitdistance) 
            FROM planets
            )
        );

进一步分析后,您将加入表卫星,但不使用任何数据,也不限制结果集。这意味着您无法从查询中获得任何好处,并且可以直接删除。

INSERT INTO hilight 
SELECT --DISTINCT probably no longer needed as we aren't artifficially creating duplicate rows
    s.starid 
FROM planets AS p
inner join stars AS s
    on s.StarID = p.starid 
WHERE s.starid=(
    SELECT 
        starid 
    FROM planets 
    WHERE orbitdistance=(
            SELECT 
                MAX(orbitdistance) 
            FROM planets
            )
        );

现在进一步分析,如果我们看一下你的WHERE条款,它似乎是多余的。在我可以简单地将最大轨道距离与行星表匹配时,我似乎没有理由两次去行星表获得你的谓词。这也消除了加入桌上明星的任何理由。

INSERT INTO hilight 
SELECT 
    p.starid 
FROM planets AS p
WHERE p.orbitdistance=
    (
    SELECT 
        MAX(orbitdistance) 
    FROM planets
    )

由于我们没有生成如此多的重复行,因此生成的查询要简单得多,应该运行得更快。我希望能够对你的查询中发生的事情有所了解。

更新:经过进一步审核,这个GalaSQL看起来非常糟糕,而且信息已经大量过时,我强烈建议不要使用它。

答案 1 :(得分:1)

您可以删除第一个选择,使其看起来像......

INSERT INTO hilight
SELECT DISTINCT p.starid 
FROM planets p
WHERE orbitdistance=(
    SELECT MAX(orbitdistance) 
    FROM planets)
 ;

您也可以删除不同的内容,除非您有特定的理由将其包括在内。

答案 2 :(得分:0)

您也可以使用CROSS Apply。

INSERT INTO hilight 
SELECT P.startid
FROM planets P
CROSS APPLY ( SELECT MAX(orbitdistance) as maxVal FROM planets ) T
WHERE P.orbitdistance = T.maxVal