[英]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
和運行時的結果。
我的一般模式
joins
在where
合並表 exists
in
explain
和實際運行時的結果
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.