0

所以假设我有这个有 4 列的表:

id  content  parent   timestamp

其中父列引用表中另一个条目的 id

我想完成以下任务:

从按以下顺序排序的表中选择前 50 行:

for each row,

if(parent = 0){
  add row to resultset, ordered by timestamp
}
else if (parent != 0){
   if parent is in the list of rows already fetched so far by the query,
   add row to resultset, ordered by the timestamp
   otherwise, wait until the parent gets fetched by the query 
   (assuming it gets fetched at all since there we're only getting the first 50 rows) 
} 

这个排序逻辑有点复杂,我想知道是否甚至可以在单个查询中使用 MYSQL ORDER BY 语句来完成这个,而不必求助于子查询?也许我们可以设置和使用变量?但是 ORDER BY 语句将如何实现呢?

4

1 回答 1

0

这是一个使用变量的解决方案,我将其合并到一个带有循环的过程中,该循环使用外连接和一个临时表来保存未使用的输入数据但没有子查询。

删除任何旧版本的程序并设置分隔符

DROP PROCEDURE IF EXISTS order_proc;
DELIMITER ;;

开始写程序

CREATE PROCEDURE order_proc()
BEGIN
DECLARE n INT DEFAULT 50;
DECLARE m INT DEFAULT 0;
DECLARE i INT DEFAULT 0;
DECLARE custom_limit INT DEFAULT 0;

DROP TABLE IF EXISTS pre_resultset;
CREATE TABLE pre_resultset LIKE input_data;
ALTER TABLE pre_resultset MODIFY id INT;
ALTER TABLE pre_resultset DROP PRIMARY KEY;
ALTER TABLE pre_resultset ADD COLUMN iid INT PRIMARY KEY NOT NULL AUTO_INCREMENT FIRST;

SELECT n INTO custom_limit;
Set SQL_SELECT_LIMIT = custom_limit;
INSERT INTO pre_resultset SELECT NULL,id, content, parent, timestamp FROM input_data WHERE parent = 0 ORDER BY timestamp;
Set SQL_SELECT_LIMIT = default;

DROP TABLE IF EXISTS unused_input_data;
CREATE TABLE unused_input_data LIKE input_data;
ALTER TABLE unused_input_data ADD null_col VARCHAR(1);
SELECT COUNT(*) FROM pre_resultset INTO m;
WHILE m<n DO 
  SELECT COUNT(*) FROM pre_resultset INTO m;
  TRUNCATE unused_input_data;
  INSERT INTO unused_input_data SELECT input_data.id, input_data.content, input_data.parent, input_data.timestamp, pre_resultset.id AS null_col FROM input_data LEFT OUTER JOIN pre_resultset on input_data.id = pre_resultset.id WHERE pre_resultset.id IS NULL ;

  SELECT n-m INTO custom_limit;
  Set SQL_SELECT_LIMIT = custom_limit;
  INSERT INTO pre_resultset SELECT NULL, unused_input_data.id, unused_input_data.content, unused_input_data.parent, unused_input_data.timestamp FROM unused_input_data JOIN pre_resultset WHERE unused_input_data.parent = pre_resultset.id ORDER BY unused_input_data.timestamp;
  Set SQL_SELECT_LIMIT = default;

  SELECT COUNT(*) FROM pre_resultset INTO i;
  SELECT (IF( i = m, n, i)) INTO m;
END WHILE;
SELECT id, content, parent, timestamp FROM pre_resultset AS resultset;
DROP TABLE IF EXISTS pre_resultset;
DROP TABLE IF EXISTS unused_input_data;
End;
;;

改回分隔符

DELIMITER ;

运行程序

CALL order_proc();
于 2013-05-07T02:18:28.503 回答