2014-10-08 127 views
3

我正在學習SQL,並且一直在經歷GalaXQL應用程序的章節。SELECT .. FROM(SELECT .. FROM ..)。我該如何改進這個查詢?

我已經寫了下面的問題來回答這個問題:「Hilight擁有星系中最高軌道距離的星球,記得在開始之前清除舊的山丘。

該查詢返回結果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)); 

我這個查詢結構

首先背後的邏輯找到從表「行星」最大的軌道距離地球。

第二將「最高軌道距離」的值與表「行星」的「軌道距離」字段進行比較,並返回與該字段有關的「星號」。

第三將表格「行星」中的字段「starid」的值與表格「星星」中的字段「starid」進行比較,然後將該「starid」插入到表格「hilight」中。

數據結構:

enter image description here

+0

嘗試更改'SELECT DISTINCT s.starid從行星AS p,星星AS s,衛星AS m WHERE ...'到:'SELECT s.starid FROM stars AS s WHERE ...' – 2014-10-08 14:11:37

+0

問題1是你正在使用[古代加入語法。](http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/bad-habits-to-kick-using-old-style-joins.aspx)也是爲什麼你在做一個交叉連接嗎?你不應該爲這些連接設置「ON」狀態嗎?如果你這樣做了,你可能也不需要那麼明顯。 – Zane 2014-10-08 14:13:41

+0

@ypercube:這會導致大量的「starid」被傳遞給「hilight」。由於「hilight」表中的「starid」是一個唯一的整數,這會導致錯誤「column starid不是唯一的」,並且不允許我進步。 但是,DISTINCT似乎是問題,在沒有DISTINCT的情況下運行查詢並且沒有嘗試將數據插入到hilight表中可以成功快速地運行。 – Awebb 2014-10-08 14:18:06

回答

7

好吧讓我們先看看您的基本查詢。我知道你已經有了一個可行的答案,但我覺得我需要向你解釋你的查詢中發生了什麼。

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似乎是相當可怕的,並有大量過時的信息,我強烈建議不要使用它。

+0

這非常有幫助,並且有很多意義,謝謝。 通過GalaXQL,在我看來,值被插入到hilight之前必須通過每個表傳遞。很顯然,情況並非如此,我有些放心,我不必處理那個特定的編程障礙。 – Awebb 2014-10-08 14:57:51

1

你可以刪除第一個選擇使得它將liook喜歡...

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

你也可以去除不同,除非你有一個特定的包括它的原因。

+0

這效果更好,謝謝。 看起來我很大程度上考慮了在表之間傳遞的過程。 – Awebb 2014-10-08 14:27:40

0

您可以使用CROSS應用。

INSERT INTO hilight 
SELECT P.startid 
FROM planets P 
CROSS APPLY (SELECT MAX(orbitdistance) as maxVal FROM planets) T 
WHERE P.orbitdistance = T.maxVal 
相關問題