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 に答える