2011-10-24 168 views
3

如何在MySQL查詢中表達:「獲取所有新元素,但至少有N個元素」。MySql:獲取至少N個元素

我會盡力解釋更好。如果我有一個產品列表[產品,價格,日期,新],我想知道如何進行查詢,並且我想向用戶顯示所有新元素,但是如果少於N個元素(例如5),則顯示最後的項目。如果能想到在這樣一個查詢:

SELECT * FROM `products` WHERE new='1' ORDER BY date DESC 

但這只是返回所有新的元素和這樣的:

SELECT * FROM `products` WHERE new='0' ORDER BY date DESC LIMIT 5 

剛剛返回所需的最小元素。

一些例子:

  • 如果表中包含4個新項目,查詢應該返回4個新項目和最新的非新項目
  • 如果表中包含7個新項目,查詢應該返回只有7個新項目
  • 如果表中包含1個新項目,則查詢應返回新項目和4個非新項目。
+0

怎樣的'new'字段從'date'領域區分?如果您按日期訂購併將結果限制爲5,那麼不會讓您獲得您想要的結果嗎?即使結果中的第五個元素不是「新」,它仍然是最新的非新項目,不是? –

+1

LIMIT查詢不可能。限制值必須是常量或變量 - 在查詢運行時不能動態填寫限制。你需要做一些客戶端按摩。 –

+1

@logan:即使有7個新/ 0舊項目顯示,它也只會返回5個項目。 –

回答

4

使用UNION組合兩個結果集。

(
    SELECT * 
    FROM `products` 
    WHERE new = '1' 
) 
UNION 
(
    SELECT * 
    FROM `products` 
    ORDER BY new DESC, date DESC 
    LIMIT 5 
) T1 
ORDER BY new DESC, date DESC 
  • UNION的第一部分返回所有的新項目。
  • UNION的第二部分返回前五個新項目,或者如果少於5個項目,則返回所有新項目,然後返回前5-n箇舊項目。
  • UNION刪除結果集中的任何重複項。

請注意,這假設在您的表的任何列或列組合上定義了唯一鍵(例如,如果您的表有一個主鍵,這應該起作用)。

+1

這就是我最初的想法。但是,即使有5個以上的新項目要顯示,這也只會限制爲5個結果。 – Genzume

+1

問題是即使有一些新結果,它也會輸出5箇舊結果。 – Karolis

+0

@Karolis:不會。它只會輸出* 5行的舊行。如果有五個或更多新行,* no *舊行將被返回。 –

0

我認爲你可以做的最好的是兩個選擇的UNION:1)所有新項目和2)最少數量的附加項目。然後在您的應用程序邏輯中決定顯示哪些行。 SQL不提供語法來完成你所要求的。

編輯:其實,或許有可能做到這一點使用用戶定義的變量。儘管如此,對於執行UNION並且已經完成的工作(對於MySQL服務器)可能更少。

1

訂單也new,不僅date

SELECT * FROM `products` ORDER BY new, date DESC 
+1

+1 Cuz我們想到了同樣的事情 - 但不要忘記限制5. – Marvo

+0

@Marvo爲什麼要限制?它說所有新元素但不少於五個元素。該查詢滿足這兩個要求。 –

0
SELECT *, @rownum := @rownum + 1 AS rownum 
FROM products, (SELECT @rownum := 0) AS vars 
ORDER BY new DESC, date DESC 
HAVING rownum <= 5 OR new = 1 
+0

我試過這個,但是如果有少於5個新項目,我不能得到它返回5個項目 – Ivan

+0

你想要NULL值嗎? –

0

select * from products order by new desc, date desc limit 5

這假定 「新」 列只會在它的1或0值。

+1

但是,如果有7個新項目,它將只返回5! :) – Ivan

0

僞代碼:

CREATE STOREPROCEDURO 
(
    @howMany INT 
) 

Declare @nNew INT 

Declare @nOld INT 

SET @nNew = (select count(*) from table where new = 1 order by date desc) 

set @nOld = (select count(*) from table where old = 1 order by date desc) 

set @nOld = @howMany - @nNew 

if (@nOld < 0) 
begin 
    @nOld = 0 
end 

(select top (@nNew) * from table where new = 1 order by date desc) 
union 
(select top (@nOld) * from table where new = 0 order by date desc) 
</code> 
相關問題