sql - 选择..来自(选择..来自..)。如何改进此查询?

标签 sql sqlite

我正在学习 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”插入表“高亮”。

数据结构:

enter image description here

最佳答案

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

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

关于sql - 选择..来自(选择..来自..)。如何改进此查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26258949/

相关文章:

php - 如何防止 PHP 中的 SQL 注入(inject)?

javascript - 按字母顺序排列歌曲列表,不区分大小写

mysql - SQL - 在复杂字段中选择整数(CAST 和 LIKE 运算符)

java - 我的表没有在 Sqlite 中创建(Toast for dataNotInserted)....下面的代码 fragment

SQLite:数据类型是否取决于引号?

sql - 如何根据 CASE 执行不同的 SELECT 语句

mysql - 如何获取姓名和经理姓名

sql - 如何获取Viditymart的产品总数?

mysql - SQL中两个表之间的计算

sqlite - SQLite FTS 表可以由 View 支持吗?