簡體   English   中英

MySQL不支持子選擇內的limit子句,我該怎么做?

[英]MySQL doesn't support the limit clause inside a subselect, how can I do that?

我在MySQL 5.1.30上有下表:

CREATE TABLE  article (
  article_id int(10) unsigned NOT NULL AUTO_INCREMENT,
  category_id int(10) unsigned NOT NULL,
  title varchar(100) NOT NULL,
  PRIMARY KEY (article_id)
);

有了此信息:

1, 1, 'foo'
2, 1, 'bar'
3, 1, 'baz'
4, 1, 'quox'
5, 2, 'quonom'
6, 2, 'qox'

對於包含文章的所有類別,我需要獲取每個類別中的前三篇文章。 像這樣:

1, 1, 'foo'
2, 1, 'bar'
3, 1, 'baz'
5, 2, 'quonom'
6, 2, 'qox'

當然,工會將起作用:

select * from articles where category_id = 1 limit 3
union
select * from articles where category_id = 2 limit 3

但是數據庫中類別的數量未知。 另外,順序應該由我在示例中省略的is_sticky和published_date列指定,以簡化。

是否可以建立一個檢索此信息的查詢?

更新:我嘗試了以下似乎可行的方法, 只是 MySQL不支持子選擇內的limit子句。 您知道模擬極限的方法嗎?

select *
  from articles a
  where a.article_id in (select f.article_id
                      from articles f
                      where f.category_id = a.category_id
                      order by f.is_sticky, f.published_at
                      limit 3)

謝謝

恐怕子查詢中不支持SELECT ... LIMIT,因此現在該介紹一下自我聯接魔術了:

SELECT article.*
FROM article
JOIN (
    SELECT a0.category_id AS id, MIN(a2.article_id) AS lim
    FROM article AS a0
    LEFT JOIN article AS a1 ON a1.category_id=a0.category_id AND a1.article_id>a0.article_id
    LEFT JOIN article AS a2 ON a2.category_id=a1.category_id AND a2.article_id>a1.article_id
    GROUP BY id
) AS cat ON cat.id=article.category_id
WHERE article.article_id<=cat.lim OR cat.lim IS NULL
ORDER BY article_id;

中間的位是通過嘗試按升序ID順序聯接同一表的三個副本來計算出每個類別的第三低ID文章的ID。 如果一個類別的文章少於三個,則左聯接將確保限制為NULL,因此外部WHERE也需要處理這種情況。

如果您的“前3名”要求可能在某個時候變為“前n名”,那么這將變得很笨拙。 在這種情況下,您可能需要重新考慮先查詢不同類別列表,然后再合並每個類別查詢的想法。

ETA:在兩列上訂購:eek,新要求! :-)

這取決於您的意思:如果您只想訂購最終結果,則可以毫無疑問地將其付諸實踐。 但是,如果您需要使用此順序來選擇要挑選的三篇文章,則要困難得多。

我們使用帶有'<'的自聯接來重現'ORDER BY article_id'所具有的效果。 不幸的是,雖然您可以執行'OR BY BY a,b',但您不能執行'(a,b)<(c,d)'...也不能執行'MIN(a,b)'。 另外,實際上需要按issticky,published article_id三列進行排序,因為您需要確保每個排序值都是唯一的,以避免返回四行或更多行。

盡管您可以通過一些粗整數或列的字符串組合來構成自己的可排序值:

LEFT JOIN article AS a1
ON a1.category_id=a0.category_id
AND HEX(a1.issticky)+HEX(a1.published_at)+HEX(a1.article_id)>HEX(a0.issticky)+HEX(a0.published_at)+HEX(a0.article_id)

這變得越來越丑陋,並且計算將浪費使用索引來提高查詢效率的任何機會。 此時,最好只進行單獨的每個類別的LIMITED查詢。

您可能應該添加另一個包含category_idcategory_id說明的表。 然后,您可以在該表中查詢類別ID的列表,並使用子查詢或其他查詢來獲取具有適當排序和限制的文章。 我現在沒有時間將其完整寫出來,但是其他人可能會寫(或者我會在不太可能的情況下這樣做,因為等到我回來時沒有人做出回應)。

這是我不感到驕傲的(在MS SQL中-不確定它是否可以在MySQL中使用)

select a2.article_id, a2.category_id, a2.title
from 
    (select distinct category_id
    from article) as a1
    inner join article a2 on a2.category_id = a1.category_id

where a2.article_id <= (
    select top 1 a4.article_id 
    from (
         select top 3 a3.article_id 
         from article a3 
         where a3.category_id = a1.category_id 
         order by a3.article_id asc
    ) a4 
    order by a4.article_id desc)

這種方式將取決於MySQL支持子查詢。 基本上,它為每個類別計算出第三大的article_id,並加入所有小於或等於每個類別的文章。

SELECT TOP n *應該和SELECT * LIMIT n一樣,我希望...

暫無
暫無

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

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