2011-10-24 95 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> 
相关问题