簡體   English   中英

SQL子查詢和ORDER BY

[英]SQL Sub Queries and ORDER BY

我正在PHPMyAdmin中學習SQL,並想弄清楚我的解決方案是否還可以,或者我做的不是最佳標准。 謝謝。

作者(ID,名字,姓氏,出生年份,性別,LivingCityID)

圖書(ID,名稱,類型,出版年,出版商ID,SoldBookCount)

寫(BookID,AuthorID)

城市(ID,城市名稱,國家/地區)

發布者(ID,PublisherName,PublisherCityID)

查找未在其作者所在城市出版的所有圖書的ID。 一本書可能有幾位作者。

SELECT w.BookID
FROM author as a, book as b, writes as w, publisher as p
WHERE a.LivingCityID != p.PublisherCityId AND w.AuthorID = a.ID AND w.BookID = b.ID AND p.ID = b.PublisherID
ORDER BY w.BookID ASC

接下來的兩個基本上是相同的,但是我認為我寫的是草率的。 有什么更好的方法可以做到這一點?

查找在1600年之前 1900年之后出版了圖書但在1600年和1900年之間未出版任何書的出版商的ID。

SELECT DISTINCT PublisherID
FROM book
WHERE PublisherID NOT IN (SELECT PublisherID
 FROM book
 WHERE YearPublished >=1600 AND YearPublished <= 1900)

查找在1600年之前 1900年之后出版書籍但在1600年和1900年之間未出版任何書籍的出版商的ID。

SELECT DISTINCT PublisherID
FROM book
WHERE PublisherID NOT IN (SELECT PublisherID
 FROM book
 WHERE YearPublished >=1600 AND YearPublished <= 1900)
      AND PublisherID IN (SELECT PublisherID
FROM book
WHERE YearPublished < 1600)
      AND PublisherID IN (SELECT PublisherID
FROM book
WHERE YearPublished > 1900)

我覺得你做得很好。 以下內容與您所做的沒有太大不同。 以下信息僅增加了不同的觀點。

第一

可以使用JOIN編寫第一個查詢,如下所示:

SELECT w.BookID
FROM book b
LEFT JOIN writes w on w.bookid = book.id
LEFT JOIN author a on a.id = w.authorid
LEFT JOIN publisher p on p.id = b.publisherid
WHERE NOT a.LivingCityID = p.PublisherCityId
ORDER BY w.BookID ASC

使用where子句過濾信息。 使用join子句顯示關系。 如果您需要所有書籍,為了便於閱讀(個人觀點,在進行左聯接時就算在內),我將其放在SQL的第一張表中。

第二

第二個查詢可以重寫為

SELECT DISTINCT publisherid
FROM book b
INNER JOIN publisher p on p.id = b.publisherid
WHERE    NOT    b.yearpublished BETWEEN 1600 and 1900

在這種情況下,我們要求在1600至1900年(包括1600至1900年)之間not出版的圖書。 我們還將書籍和出版商聯系在一起,以獲取出版商信息。

編寫此查詢的另一種方法是:

SELECT DISTINCT publisherid
FROM publisher p
WHERE EXISTS (
    SELECT 1 
    FROM book 
    WHERE    NOT    yearpublished BETWEEN 1600 and 1900
        AND publisherid = p.id
)

在這里,我們要求出版商表格檢查書中是否有符合我們特定需求的記錄。 如果是,那就很好...進行選擇。 否則,繼續下一條記錄。

不錯的閱讀: http : //weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx 即使該博客是有關SQL Server的,該哲學仍然適用。

第三

您的查詢看起來很好。 以下是使用exists關鍵字添加的示例。

SELECT DISTINCT publisherid
FROM publisher p
WHERE EXISTS (
    SELECT 1 
    FROM book 
    WHERE    NOT    yearpublished BETWEEN 1600 and 1900
        AND publisherid = p.id
) 
AND EXISTS (
    SELECT 1 
    FROM book 
    WHERE yearpublished < 1600
        AND publisherid = p.id
)
AND EXISTS (
    SELECT 1 
    FROM book 
    WHERE yearpublished > 1900
        AND publisherid = p.id
)

in子句的處理方式是,如果有成千上萬個滿足>1900的Publisherid滿足條件,則查詢速度可能會變慢(也取決於優化程序)。 exists子句可以幫助克服in某些限制。

替代的編寫方式是:

SELECT publisherid
FROM 
(
    SELECT DISTINCT 
        CASE WHEN yearpublished < 1600 THEN 1600 ELSE 1900 END AS yr,
        publisherid
    FROM book b
    INNER JOIN publisher p on p.id = b.publisherid
    WHERE    NOT    b.yearpublished BETWEEN 1600 and 1900
) t
GROUP BY yr
HAVING COUNT(*) = 2

在這里,我們創建一個子查詢,並為其賦予別名t 此子查詢將書籍和出版商結合在一起,並忽略不需要出版年份的記錄。 選擇發布者ID,並使用case語句作為標記。 <1600年標記為1600。> 1900年標記為1900。這樣得出的結果如下:

1600  publisherid#1
1600  publisherid#1
1900  publisherid#1
1600  publisherid#2
1600  publisherid#3
1900  publisherid#3
...

使用distinct,我們將結果縮短為:

1600  publisherid#1    |
1900  publisherid#1    | --> this and above record will become a group
1600  publisherid#2
1600  publisherid#3    |
1900  publisherid#3    | --> this and above record will become a group
...

現在,我們按發布者ID分組,並僅要求計數為2的那些發布者ID。在上面的示例中,#1和#3將符合我們的條件。

注意

這些查詢未經測試。 它們只是展示了編寫查詢的不同方式並強調了某些差異。 哪一個快,哪一個慢? -這取決於您的數據,索引以及explain和運行時的結果。

我的一般模式

  • 使用joinswhere合並表
  • 使用exists in
  • 用虛擬數據集檢查explain和實際運行時的結果
  • 添加索引以涵蓋分組,過濾和排序
  • 添加索引提示以查看查詢是否使用我們提示使用的索引執行得更快

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM