【问题标题】:SELECT .. FROM (SELECT .. FROM ..). How can I improve this query? [duplicate]选择..来自(选择..来自..)。如何改进此查询? [复制]
【发布时间】:2014-12-03 05:37:28
【问题描述】:

我正在学习 SQL,并且已经阅读了 GalaXQL 应用程序的各个章节。

我写了以下查询来回答“突出显示星系中轨道距离最长的行星的恒星(或恒星)。记得在开始之前清除旧的亮点。”

这个查询返回的结果是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));

我在这个查询结构背后的逻辑

首先找到距离表“行星”轨道距离最大的行星。

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

第三将“planets”表中“starid”字段的值与“stars”表中“starid”字段的值进行比较,然后将该“starid”插入表“高亮”。

数据结构:

【问题讨论】:

  • 尝试将SELECT DISTINCT s.starid FROM planets AS p, stars AS s, moons AS m WHERE...更改为:SELECT s.starid FROM stars AS s WHERE...
  • 问题 1 是您正在使用 ancient join syntax. 以及为什么要进行交叉连接?您不应该为这些连接设置ON 条件吗?如果你这样做了,你可能也不需要那种独特的东西。
  • @ypercube:这会导致“starid”的大量副本被传递给“hilight”。由于“hilight”表中的“starid”是一个唯一整数,这会导致错误“column starid is not unique”并且不允许我继续。但是,DISTINCT 似乎确实是个问题,在没有 DISTINCT 的情况下运行查询并且没有尝试将数据插入到 hilight 表中,运行成功且快速。
  • @Awebb 问题确实说“(或星号)”,所以我们预计会有多个结果。
  • @Awebb 你会得到很多值,因为你正在做一个cross join。这让我回到了我原来的观点。你需要修复你的JOIN's!

标签: sql sqlite


【解决方案1】:

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

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 似乎非常糟糕,并且信息大量过时,我强烈建议不要使用它。

【讨论】:

  • 这很有帮助,也很有意义,谢谢。在我看来,通过 GalaXQL,值必须在插入到 hilight 之前通过每个表。显然情况并非如此,我感到有些欣慰的是,我不必处理那个特定的编程障碍。
【解决方案2】:

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

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

您也可以删除独特的,除非您有特定的理由来包含它。

【讨论】:

  • 这工作效率更高,谢谢。看起来我在考虑表格之间传递的过程。
【解决方案3】:

您也可以使用 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

【讨论】:

    猜你喜欢
    • 2014-10-22
    • 1970-01-01
    • 1970-01-01
    • 2015-05-28
    • 2020-08-02
    • 1970-01-01
    • 2012-08-18
    • 1970-01-01
    • 2020-09-03
    相关资源
    最近更新 更多