如何更好地进行此查询?

时间:2013-08-26 22:54:52

标签: sql sqlite group-by having-clause

我正在通过GALAXQL http://sol.gfxile.net/galaxql.html

学习SQL

我在第17课 - GROUP BY / HAVING

以下是该方案:

  

让我们看看我们尚未涉及的几个SELECT操作,   即GROUP BY和HAVING。

     

这些操作的语法如下所示:

SELECT columns FROM table GROUP BY column HAVING expression
  

SELECT中的GROUP BY命令会导致多个输出行   合并成一排。例如,如果这个非常有用   我们希望以表格的形式生成新的统计数据。

     

例如,从星星中找出最高强度   上课,我们会这样做:

Select Class, Max(Intensity) As Brightness From Stars Group By Class Order By Brightness Desc
  

HAVING操作符与WHERE的工作方式几乎相同,除外   在分组完成后应用它。因此,我们可以   计算每个类的亮度之和,并裁剪出类   其中总和高于150。

SELECT class, SUM(intensity) AS brightness FROM stars GROUP BY class HAVING brightness < 150 ORDER BY brightness DESC
  

我们可以引用未在HAVING子句中选择的列,   但结果可能难以理解。你应该可以   使用HAVING子句中的聚合函数(例如,   亮度&lt; MAX(亮度)* 0.5,但这似乎会使电流崩溃   SQLite的版本。

     

与联接结合使用时,GROUP BY变得非常方便。要找出答案   每颗恒星的行星数量,我们可以做到:

SELECT stars.starid AS starid, COUNT(planets.planetid) AS planet_count FROM planets, stars WHERE stars.starid=planets.starid GROUP BY stars.starid

Hilight是大多数轨道的恒星(行星和卫星的组合)。 (请注意,验证查询有点重,所以请耐心等待 按“好的,我已经完成......”)。


这是我的回答

SELECT stars.starid AS HighStar, 
(COUNT(planets.planetid) + COUNT(moons.moonid)) AS OrbitalsTotal 
FROM stars
LEFT OUTER JOIN planets
ON stars.starid = planets.starid
LEFT OUTER JOIN moons
ON planets.planetid = moons.planetid
GROUP BY stars.starid
ORDER BY OrbitalsTotal DESC;

此查询向我显示具有最多oribtals的恒星有170个轨道

那么:

INSERT INTO hilight SELECT result.HighStar
FROM result
INNER JOIN stars
ON result.HighStar = stars.starid
WHERE result.OrbitalsTotal = 170

我的问题是如何让这个查询更好?我不想硬编码170轨道,我不想创建第二个查询来插入数据。

5 个答案:

答案 0 :(得分:1)

SELECT stars.starid AS HighStar, 
       (COUNT(planets.planetid) + COUNT(moons.moonid)) AS OrbitalsTotal 
FROM stars
     LEFT OUTER JOIN
     planets ON stars.starid = planets.starid
     LEFT OUTER JOIN
     moons ON planets.planetid = moons.planetid
GROUP BY stars.starid
HAVING OrbitalsTotal = (SELECT MAX(Orbitals)
                        FROM (SELECT (COUNT(planets.planetid) + COUNT(moons.moonid)) Orbitals
                              FROM stars
                                   LEFT OUTER JOIN
                                   planets ON stars.starid = planets.starid
                                   LEFT OUTER JOIN
                                   moons ON planets.planetid = moons.planetid
                              GROUP BY stars.starid))

答案 1 :(得分:1)

只需使用您的第一个查询,并添加条款LIMIT 1以仅返回第一条记录:

INSERT INTO hilight
SELECT stars.starid AS HighStar
FROM stars
LEFT OUTER JOIN planets
ON stars.starid = planets.starid
LEFT OUTER JOIN moons
ON planets.planetid = moons.planetid
GROUP BY stars.starid
ORDER BY COUNT(planets.planetid) + COUNT(moons.moonid) DESC
LIMIT 1

答案 2 :(得分:1)

Star 22336没有170个轨道。

它有97个轨道。

检查卫星数量。

SELECT COUNT(moons.moonid) as moon_count
FROM stars JOIN planets
ON stars.starid=planets.starid
JOIN moons
ON planets.planetid=moons.planetid
WHERE stars.starid=22336

这给了79个卫星。

现在检查一下行星的数量。

SELECT COUNT(planets.planetid) AS planet_count
FROM stars JOIN planets
ON stars.starid=planets.starid
WHERE stars.starid=22336

这给了18个行星。

下面的SQL正确计算轨道计数并完成任务。

INSERT INTO hilight
SELECT pc.starid FROM

(SELECT p.starid, COUNT(p.planetid) AS p_count
FROM planets AS p
GROUP BY p.starid) AS pc

JOIN

(SELECT p.starid, COUNT(m.moonid) AS m_count
FROM planets AS p JOIN moons AS m
ON p.planetid=m.planetid
GROUP BY p.starid) AS mc

ON pc.starid=mc.starid

ORDER BY p_count+m_count DESC
LIMIT 1

答案 3 :(得分:0)

如果您使用SELECT TOP(1) ...开始第一个查询,那么这将只为您提供第一个结果。 TOP()语法可以与硬编号一起使用,该编号可以提供许多行或百分比,从而提供总数的百分比。

答案 4 :(得分:0)

通过GalaXQL的第17章,我们还没有学到LIMIT,而且我认为我们可以在没有所有LEFT OUTER JOINS的情况下做到这一点(借用Dale M&#39;其中缺少&#34; AS&# 34;之前&#34; Orbitals&#34;虽然它仍然有效?!))与我们在该部分的最后一个例子中看到的更接近。

那怎么样:

DELETE FROM hilight;
INSERT INTO hilight 
SELECT HighStar FROM (
    SELECT stars.starid AS HighStar, 
        (COUNT(planets.planetid) + COUNT(moons.moonid)) AS OrbitalsTotal 
    FROM stars, planets, moons 
    WHERE stars.starid = planets.starid
        AND planets.planetid = moons.planetid
    GROUP BY stars.starid
    HAVING OrbitalsTotal = (
        SELECT MAX(Orbitals) FROM (
            SELECT (COUNT(planets.planetid) + COUNT(moons.moonid)) AS Orbitals
            FROM stars, planets, moons
            WHERE stars.starid = planets.starid
                AND planets.planetid = moons.planetid
            GROUP BY stars.starid))
);
SELECT * FROM hilight;

使用LIMIT,我们也可以避免LEFT OUTER JOIN而不必复制我们的选择:

DELETE FROM hilight;
INSERT INTO hilight
SELECT bodygroup FROM (
    SELECT stars.starid as bodygroup, 
        (COUNT(planets.planetid)+COUNT(moons.moonid)) AS bodycount
    FROM stars, planets, moons 
    WHERE stars.starid=planets.starid 
        AND planets.planetid=moons.planetid 
    GROUP BY stars.starid
    ORDER BY bodycount DESC) 
LIMIT 1;
SELECT * FROM hilight;

或者使用CREATE VIEW试图避免在不使用LIMIT的情况下加倍努力,我们可以:

DELETE FROM hilight;    
CREATE VIEW bodyview AS
    SELECT stars.starid as bodygroup,
        (COUNT(planets.planetid)+COUNT(moons.moonid)) AS bodycount
    FROM stars, planets, moons
    WHERE stars.starid=planets.starid
       AND planets.planetid=moons.planetid
    GROUP BY stars.starid
    ORDER BY bodycount DESC;
INSERT INTO hilight SELECT bodygroup FROM bodyview  
    WHERE bodycount = (SELECT MAX(bodycount) FROM bodyview );
DROP VIEW bodyview;
SELECT * FROM hilight;