2013-08-26 105 views
2

我正在學習SQL通過GALAXQL http://sol.gfxile.net/galaxql.html如何使這個查詢更好?

林在第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 

的擁有操作的工作幾乎方法一樣WHERE,除了 那它在分組完成後應用。因此,我們可以計算出 每級亮度的總和,並裁掉類 其中總和比,說高,150

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

我們可以引用列未選擇在HAVING子句中, 但結果可能難以理解。您應該能夠 使用HAVING子句在聚合函數(例如, 亮度< MAX(亮度)* 0.5,但是這似乎崩潰當前 版本的SQLite。

當結合聯接,GROUP通過變得相當方便的找出 每星行星的數量,我們可以做:

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

高亮大多數軌道(組合行星和衛星)的星 (注意驗證查詢一世有點沉重,所以請耐心等待 按下「好吧,我完成了......」)。


這裏是我的回答

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軌道,我不想創建第二個查詢來插入數據。

+0

奇怪的是,回答問題的最好方法是不使用having子句。 SQLite是否支持派生表,這是一個帶有別名的子查詢? –

+0

@DanBracuk是的,'SELECT ... FROM(SELECT ...)別名...'支持。 –

+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)) 
+0

該解決方案錯誤地計算了行星的數量。簡而言之,COUNT(planets.planetid)計算諸如(衛星數量+沒有衛星的行星數量)。有關正確的解決方案,請參閱https://stackoverflow.com/a/34543612/532954。 – user532954

0

如果你用SELECT TOP(1) ...開始你的第一個查詢,那麼這將只給你第一個結果。 TOP()語法可以與一個硬編號一起使用,該編號給出了很多行或佔總數百分比的百分比。

+0

我嘗試了SQL lite的頂級版本,並得到了一個沒有TOP功能的錯誤。但是,想象一下這是行得通的,在hilights表中只有一列,而在第一個查詢中只有SELECT(ing)兩列。那麼我怎樣才能讓彗星進入太空桌呢? –

+0

而不是添加另一個答案,你應該更新/編輯這一個。 – Omar

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 
0

通過GalaXQL的第17章中,我們還沒有學會限制,我想我們可以在沒有所有LEFT OUTER JOINS的情況下(從Dale M借用(它在「Orbitals」之前缺少「AS」,儘管它仍然有效!))與我們在該部分的最後一個例子中看到的有點接近。

因此,如何:

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; 

有了限制,我們也避免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; 
+0

這些解決方案也錯誤地將軌道數計算爲2n_moons + n_planets_without_moons。請參閱此處以獲得正確的解決方案:https://stackoverflow.com/a/34543612/532954 – user532954

1

星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 
+0

此解決方案正確計算軌道數。 – user532954