是否可以在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.我需要的是来自数量'的5个结果的样本。 3,5和7.即。我需要结果看起来像:
'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
答案 0 :(得分:2)
不,在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 ...
相关子查询可能会被执行很多次,因此为了获得最佳性能,您需要一个包含number
和qty
前导列的索引,并包含{{1} }专栏。
或者:
a_id
或
... ON `_mct_dot` (`number`, `qty`, `a_ID`)
另一种选择是使用MySQL用户变量来模拟... ON `_mct_dot` (`qty`, `number`, `a_ID`)
分析函数,如下所示:
row_number()
(这些查询仅限桌面检查;尚未设置SQL Fiddle演示。)
<强>后续强>
对于第一个查询,我刚刚使用了内联视图(别名为“p”),它生成了所请求的所有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
和number
值对的集合。 / p>
我们可以使用JOIN操作来查找与_mct_dot表中每对匹配的所有行。
棘手的部分是相关子查询。 (我们可以使用几种方法。)上面查询中的方法是获得具有匹配“number”和“qty”的行的“计数”,但id值小于id的值。当前行,基本上找出当前行“之前”有多少行。我们将它与文字5进行比较,因为我们只希望返回每组中的前5行。
对于第二个查询,
以 qty
为别名的内联视图正在初始化一些MySQL用户变量。我们并不关心查询返回什么,除了它只返回一行(因为我们在JOIN操作中引用它)...我们真正感兴趣的是在开始时初始化变量执行。这是因为MySQL在执行引用视图的外部查询之前实现了内联视图(派生表)。
内联视图别名为 i
,为我们提供了我们想要检索的p
对,我们对_mct_dot使用JOIN操作来获取匹配的行。
内联视图中的“技巧”别名为 number,qty
是使用MySQL用户变量。我们正在检查当前值与前一行的值...如果数字和数量匹配,那么我们在同一个“组”中,所以我们可以将行数计数器增加1。任何一个值都会改变,那么它就是一个新组,所以我们将行号计数器重置为1,因为当前行是新组中的“第一”行。
我们可以针对内嵌视图 s
运行查询,并看到我们得到行号(s
col)1,2,3等。对于每个小组。
然后,最外面的查询只过滤掉rn
行号大于5的所有行。实际上,从 rn
,我们只返回行的唯一标识符;最外层的查询也在做一个JOIN操作,根据唯一的id来检索整行。
正如我在答案的顶部提到的,执行此操作的SQL并不漂亮。 (取消这些查询正在进行的操作需要花费一些工作。)
答案 1 :(得分:0)
我不确定我是否理解你的问题,因为它不是很清楚,但根据我所理解的情况,我认为你可以尝试这样的事情:
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
希望这有帮助!!!