[英]LIMIT SQL within WHERE clause?
是否可以在sql的WHERE子句中放置限制?
表名称: _mct_dot
列: a_ID (auto inc) number (index) qty (index) com_val
SELECT
*
FROM
_mct_dot
WHERE
(
number = 4
OR
number = 7
OR
number = 13
)
AND
(
qty = 3
OR
qty = 5
OR
qty = 7
)
ORDER BY
number ASC, qty ASC
因此,上面的查询实际上将返回按顺序分组的数组。 但是,它将提取值3、5和7的所有“数量”。我需要的是“数量” 3、5和7的5个结果的样本。 我需要结果看起来像:
'number' 4's with 'qty' = 3's where 'qty' limited to max 5
'number' 4's with 'qty' = 5's where 'qty' limited to max 5
'number' 4's with 'qty' = 7's where 'qty' limited to max 5
'number' 7's with 'qty' = 3's where 'qty' limited to max 5
'number' 7's with 'qty' = 5's where 'qty' limited to max 5
'number' 7's with 'qty' = 7's where 'qty' limited to max 5
'number' 13's with 'qty' = 3's where 'qty' limited to max 5
'number' 13's with 'qty' = 5's where 'qty' limited to max 5
'number' 13's with 'qty' = 7's where 'qty' limited to max 5
不,不可能在WHERE子句中添加LIMIT
子句。
可以实现所需的结果集,但是执行此操作的SQL并不是很漂亮。 这将需要JOIN,相关子查询或内联视图。
如果_mct_dot中的行有一个“顺序”,则可以使用相关子查询来检查拉出的行“之前”的行数,并仅获取少于四行的行。
SELECT d.*
FROM _mct_dot d
JOIN ( SELECT n.number
, q.qty
FROM (SELECT 4 AS `number` UNION ALL SELECT 7 UNION ALL SELECT 13) n
CROSS
JOIN (SELECT 3 AS `qty` UNION ALL SELECT 5 UNION ALL SELECT 7) q
) p
ON p.number = d.number
AND p.qty = d.qty
AND 5 > ( SELECT SUM(1)
FROM _mct_dot c
WHERE c.number = d.number
AND c.qty = d.qty
AND c.a_ID < d.a_ID
)
ORDER BY ...
相关的子查询可能会被执行很多次,因此为了获得最佳性能,您将需要一个索引,该索引的前导a_id
number
和qty
并包括a_id
列。
要么:
... ON `_mct_dot` (`number`, `qty`, `a_ID`)
要么
... ON `_mct_dot` (`qty`, `number`, `a_ID`)
另一个选择是使用MySQL用户变量来模拟row_number()
分析函数,如下所示:
SELECT t.*
FROM ( SELECT d.a_ID
, IF(d.number = @prev_number AND d.qty = @prev_qty
, @rn := @rn + 1
, @rn := 1
) AS rn
, @prev_number := d.number
, @prev_qty := d.qty
FROM (SELECT @prev_number := NULL, @prev_qty := NULL, @rn := 0 ) i
CROSS
JOIN ( SELECT n.number
, q.qty
FROM (SELECT 4 AS `number` UNION ALL SELECT 7 UNION ALL SELECT 13) n
CROSS
JOIN (SELECT 3 AS `qty` UNION ALL SELECT 5 UNION ALL SELECT 7) q
) p
JOIN _mct_dot d
ON d.number = p.number
AND d.qty = p.qty
ORDER BY d.number, d.qty
) s
JOIN _mct_dot t
ON t.a_ID = s.a_ID
WHERE s.rn <= 5
ORDER BY t.number ASC, t.qty ASC
(这些查询仅在桌面进行检查;尚未设置SQL Fiddle演示。)
跟进
对于第一个查询,我只使用了一个内联视图(别名为“ p”),该视图生成了所请求的所有成对的number
和qty
对的集合。
我们可以使用JOIN操作从_mct_dot表中找到与每对匹配的所有行。
棘手的部分是相关子查询。 (我们可以使用两种方法。)上面查询中的方法是获取具有匹配的“数字”和“数量”但其ID值小于该ID值的行的“计数”当前行,基本上是找出当前行“之前”有多少行。 我们将其与文字5进行比较,因为我们只想返回每个组中的前5行。
对于第二个查询,
由于i
正在初始化一些MySQL用户变量,因此内联视图具有别名。 我们真的不在乎查询返回什么,除了它只返回一行(因为我们在JOIN操作中引用它)...我们真正感兴趣的是在变量的开头初始化变量。执行。 发生这种情况的原因是,在执行引用该视图的外部查询之前,MySQL实现了内联视图(派生表)。
别名为p
的内联视图为我们提供了要检索的number,qty
对number,qty
,我们对_mct_dot使用JOIN操作来获取匹配的行。
内联视图中别名为s
的“技巧”是使用MySQL用户变量。 我们正在根据前一行的值检查当前值...如果数量和数量匹配,那么我们在同一个“组”中,因此我们可以将行计数器增加1。这两个值都会更改,然后是一个新组,所以我们将行号计数器重置为1,因为当前行是新组中的“第一”行。
我们可以对内联视图s
运行查询,并看到我们正在为每个组获取行号( rn
col)1、2、3等。
然后,最外面的查询仅过滤rn
号大于5的所有行。 实际上,从s
,我们仅返回该行的唯一标识符; 该最外面的查询也在执行基于唯一ID的JOIN操作来检索整行。
正如我在回答的顶部提到的那样,执行此操作的SQL并不漂亮。 (解开这些查询的工作确实需要一些工作。)
由于不确定性不明确,我不确定我是否正确理解了您的问题,但是根据我的理解,我认为您可以尝试执行以下操作:
SELECT attribute_number,
grade_number //, other columns
FROM _mct_dot
WHERE (number = 4 AND qty IN (3, 5 ,7))
OR (number = 7 AND qty IN (3, 5, 7))
OR (number = 13 AND qty IN (3, 5, 7))
GROUP BY attribute_number, grade_number
ORDER BY attribute_number ASC, grade_number ASC
LIMIT 5
希望这可以帮助!!!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.