2014-10-08 88 views
3

我正在学习SQL,并且一直在经历GalaXQL应用程序的章节。SELECT .. FROM(SELECT .. FROM ..)。我该如何改进这个查询?

我已经写了下面的问题来回答这个问题:“Hilight拥有星系中最高轨道距离的星球,记得在开始之前清除旧的山丘。

该查询返回结果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)); 

我这个查询结构

首先背后的逻辑找到从表“行星”最大的轨道距离地球。

第二将“最高轨道距离”的值与表“行星”的“轨道距离”字段进行比较,并返回与该字段有关的“星号”。

第三将表格“行星”中的字段“starid”的值与表格“星星”中的字段“starid”进行比较,然后将该“starid”插入到表格“hilight”中。

数据结构:

enter image description here

+0

尝试更改'SELECT DISTINCT s.starid从行星AS p,星星AS s,卫星AS m WHERE ...'到:'SELECT s.starid FROM stars AS s WHERE ...' – 2014-10-08 14:11:37

+0

问题1是你正在使用[古代加入语法。](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using-old-style-joins.aspx)也是为什么你在做一个交叉连接吗?你不应该为这些连接设置“ON”状态吗?如果你这样做了,你可能也不需要那么明显。 – Zane 2014-10-08 14:13:41

+0

@ypercube:这会导致大量的“starid”被传递给“hilight”。由于“hilight”表中的“starid”是一个唯一的整数,这会导致错误“column starid不是唯一的”,并且不允许我进步。 但是,DISTINCT似乎是问题,在没有DISTINCT的情况下运行查询并且没有尝试将数据插入到hilight表中可以成功快速地运行。 – Awebb 2014-10-08 14:18:06

回答

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似乎是相当可怕的,并有大量过时的信息,我强烈建议不要使用它。

+0

这非常有帮助,并且有很多意义,谢谢。 通过GalaXQL,在我看来,值被插入到hilight之前必须通过每个表传递。很显然,情况并非如此,我有些放心,我不必处理那个特定的编程障碍。 – Awebb 2014-10-08 14:57:51

1

你可以删除第一个选择使得它将liook喜欢...

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

你也可以去除不同,除非你有一个特定的包括它的原因。

+0

这效果更好,谢谢。 看起来我很大程度上考虑了在表之间传递的过程。 – Awebb 2014-10-08 14:27:40

0

您可以使用CROSS应用。

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