David Folksman David Folksman - 4 years ago 117
SQL Question

How can I make this query better?

I'm learning SQL through GALAXQL http://sol.gfxile.net/galaxql.html

Im on lesson 17 - GROUP BY/HAVING

Here is the scenario:


Let's look at couple of SELECT operations we haven't covered yet,
namely GROUP BY and HAVING.

The syntax for these operations looks like this:


SELECT columns FROM table GROUP BY column HAVING expression



The GROUP BY command in a SELECT causes several output rows to be
combined into a single row. This can be very useful if, for example,
we wish to generate new statistical data as a table.

For example, to find out the highest intensities from stars for each
class, we would do:


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



The HAVING operator works pretty much the same way as WHERE, except
that it is applied after the grouping has been done. Thus, we could
calculate the sum of brightnesses per class, and crop out the classes
where the sum is higher than, say, 150.


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



We could refer to columns that are not selected in the HAVING clause,
but the results might be difficult to understand. You should be able
to use the aggregate functions in the HAVING clause (for example,
brightness < MAX(brightness)*0.5, but this seems to crash the current
version of SQLite.

When combined with joins, GROUP BY becomes rather handy. To find out
the number of planets per star, we can do:


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


Hilight the star with most orbitals (combined planets and moons).
(Note that the validation query is somewhat heavy, so be patient after
pressing "Ok, I'm done..").





Here was my answer

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;


This query showed me that the star with the most oribtals has 170 orbitals

So then:

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


My question to you is how can I make this query better? I don't want to have to hard code the 170 orbitals and I dont want to have to create a second query to insert the data.

Answer Source
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))
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download