我正在使用MySQL执行数据库事务,并使用PHP运行MySQL查询。我想按以下顺序使用stack1
列的值(0、0、0、1、1、1、1、1、1、0、0、0,...)来获取查询结果。我想按where
列的值按3:6的比例获取记录。
有没有办法实现这一目标?
我搜索了不同的算法,但没有找到符合我要求的内容。我找到了唯一一个由替代记录引发结果的查询,但是我的要求没有得到满足。
我希望输出类似
function readDocuments(collection, options = {}) {
let {where, orderBy, limit} = options;
let query = firebase.firestore().collection(collection);
if (where) {
if (where[0] instanceof Array) {
// It's an array of array
for (let w of where) {
query = query.where(...w);
}
} else {
query = query.where(...where);
}
}
if (orderBy) {
query = query.orderBy(...orderBy);
}
if (limit) {
query = query.limit(limit);
}
return query
.get()
.then()
.catch()
}
// Usage
// Multiple where
let options = {where: [["category", "==", "someCategory"], ["color", "==", "red"], ["author", "==", "Sam"]], orderBy: ["date", "desc"]};
//OR
// A single where
let options = {where: ["category", "==", "someCategory"]};
let documents = readDocuments("books", options);
答案 0 :(得分:1)
您需要与ROW_NUMBER() OVER (PARTITION BY is_free ORDER BY id)
类似的内容。一旦有了每个分区的行号(例如0-0、0-1、0-2、0-3,...,1-0、1-1、1-2、1-3,... ),您可以使用基本数学对结果进行排序(值0-0 ... 0-2和1-0 ... 1-5排在最前面,0-3 ... 0-5和1-6 ... 1-11排名第二,依此类推。不幸的是,MySQL 5.x不支持窗口函数,因此您需要使用某种技巧来计算行数。这是一个:
SELECT *
, rn div IF(is_free = 1, 6, 3) AS gn
FROM (
SELECT id
, is_free
, (SELECT COUNT(*) FROM t AS x WHERE x.id < t.id AND x.is_free = t.is_free) AS rn
FROM t
) AS x
ORDER BY gn, is_free
答案 1 :(得分:0)
在MySQL 8+中,您可以使用:
order by floor( (row_number() over (partition by is_free order by id) - 1) / 4),
is_free, id
row_number()
上的算术将它们分批处理。您可以对早期版本中的变量执行类似的操作:
select t.id, t.is_free
from (select t.*,
(@rn := if(@if = is_free, @rn + 1,
if(@if := is_free, 1, 1)
)
) as rn
from (select t.* from t order by is_free, id) t cross join
(select @if := -1, @rn := 0) params
) t
order by floor((rn - 1) / 4), is_free, id;
答案 2 :(得分:0)
select id,is_free,rank
from (
(
select id,is_free,if(@row_num = @target,@target := @target + 9,@target := @target + 0) as target,if(@target - @row_num > 3,@row_num := @row_num + 7,@row_num := @row_num + 1) as rank
from test,(select @row_num := 0,@target := 3) t2
where is_free = 0
)
union
(
select id,is_free,if(@row_num2 = @target2,@target2 := @target2 + 9,@target2 := @target2 + 0) as target,if(@target2 - @row_num2 > 8,@row_num2 := @row_num2 + 4,@row_num2 := @row_num2 + 1) as rank
from test,(select @row_num2 := 3,@target2 := 9) t3
where is_free = 1
)
) derived
order by rank,is_free,id;
演示: https://www.db-fiddle.com/f/pc9oCwwtWjacETVeGCMtcw/0
上面的想法是给每行rank
,使我们可以保持3:6的比率。
如果我们仔细观察,0
遵循一系列1 , 2 , 3 , 10 , 11 , 12 , 19 , 20 , 21
,1
遵循一系列4, 5, 6, 7, 8, 9, 13, 14, 15, 16, 17, 18, 22, 23 ...
,如下所示:
系列:
0 0 0 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 0 0 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
因此,在上述查询中,我们首先获取0
的所有记录,并以上述方式从1
开始为其分配行号。然后,通过分配从1
开始的行号,以相同的方式获取is_free = 4
的所有记录。
最后,我们使用并集合并两个结果并按其排名对其进行排序。