2017-08-23 3 views
2

SQLiteでは、LIMITの引数として整数を返すか、整数に変換できる任意の式を使用できます。SQLiteのLIMITの値として周囲のクエリの列を使用するにはどうすればよいですか?

LIMIT句では、整数または無損失で整数に変換できる値に評価される限り、スカラー式を使用できます。

SELECT * FROM event_attendees 
WHERE dtime IS NULL 
ORDER BY rtime ASC 
LIMIT (
    SELECT max_participants FROM `events` WHERE id = 1 
); 

このクエリを実行し、結果を返します:[...]を意味

、可能である以下の(Iは、さらに以下のように使用するデータベースを紹介します)。

しかし、これをサブクエリの内部で使用しようとしていますが、それによってエラーメッセージが表示されます。

SELECT * 
    FROM `events` e 
     JOIN 
     event_attendees ON `events`.id = event_attendees.event_id AND 
      event_attendees.id IN (
       SELECT id 
        FROM event_attendees ea2 
        WHERE ea2.dtime IS NULL AND 
         ea2.event_id = e.id 
        ORDER BY rtime ASC 
        LIMIT e.max_participants 
      ); 

SQLFiddleのエラーメッセージは次のとおりです。

文を準備できなかった(1いいえ、そのようなコラム:e.max_participants)

私はSQLiteStudio 3でそれを実行すると、エラーメッセージはこれです:SQLクエリの実行中

エラーデータベース 'foo':そのような列のイベントはありません..max_participants

私が実行しているスキーマは、次のようになります。

CREATE TABLE `events` (
    id    INTEGER PRIMARY KEY AUTOINCREMENT, 
    name    VARCHAR, 
    max_participants INT 
); 

CREATE TABLE event_attendees (
    id   INTEGER PRIMARY KEY AUTOINCREMENT, 
    event_id INTEGER REFERENCES events (id), 
    attendee_id INTEGER, /* we don't need attendees for this example */ 
    rtime  DATETIME NOT NULL, 
    dtime  DATETIME 
); 

次の値の例を使用します。

INSERT INTO `events` (id, name, max_participants) 
VALUES    (1, 'foo', 3), 
        (2, 'bar', 4); 

INSERT INTO `event_attendees` 
(id, event_id, attendee_id, rtime,     dtime) VALUES 
(1, 1,  1,   '2017-08-02 08:08:00', NULL    ), 
(2, 1,  2,   '2017-08-02 08:09:00', NULL    ), 
(3, 1,  3,   '2017-08-02 08:10:00', NULL    ), 
(4, 1,  4,   '2017-08-02 08:12:00', NULL    ), 
(5, 2,  1,   '2017-08-03 08:08:00', NULL    ), 
(6, 2,  2,   '2017-08-03 08:09:00', '2017-08-04 10:08:00'), 
(7, 2,  3,   '2017-08-03 08:10:00', NULL    ), 
(8, 2,  4,   '2017-08-03 08:11:00', NULL    ), 
(9, 2,  5,   '2017-08-03 08:12:00', NULL    ), 
(10, 2,  6,   '2017-08-03 08:13:00', NULL    ), 
(11, 2,  7,   '2017-08-03 08:14:00', NULL    ), 
(12, 2,  8,   '2017-08-03 08:15:00', NULL    ); 

また、an SQLFiddle with this exact data and both these queriesも用意しました。

表には、参加している人々のイベントのリストが記載されています。 attendee_idに関連するユーザーのテーブルは問題に関連していないので、私はそれを断念しました。

イベントに初めて登録した人(rtime)をキャンセルしようとしていません(dtime)、イベントのmax_participants参加者限定で制限されています。結果は、event_attendees.idの行です。

id event_id attendee_id 
1 1  1 
2 1  2 
3 1  3 
5 2  1 
7 2  3 
8 2  4 
9 2  5 

SQLiteのは、サブクエリ内の外側のクエリからe.max_participants列を見ることができないように思えます。

何か不足していますか、私が気付いていない制限があるため、これはできませんか?これに別の方法がありますか?

答えて

2

これはコメントには長すぎます。

SQLiteは制限の発現のために、実際describeルールを行います

任意のスカラー式はLIMIT句しかし、scalar expressionは、ドキュメントに定義されていない

に使用することができます。私はそれのより良い記述が "スカラー定数"であると思う。

あなたが最初のクエリを変更した場合:

SELECT ea.* 
FROM event_attendees ea 
WHERE dtime IS NULL 
ORDER BY rtime ASC 
LIMIT (SELECT e.max_participants FROM `events` e WHERE e.id = ea.event_id); 

その後、あなたはSQLiteのパーサを持っている問題を理解するであろう。 LIMITは定数である必要がありますが、1つの行から次の行に変更されます。

SQLiteはこれを拡張して、相関サブクエリを許可しないように見えます。私はSQLiteの内部を完全に理解していません。 LIMIT句は、SELECTクエリが解析されて実行される前に解析されて実行されると想像することができます。したがって、外部クエリからテーブルを使用することはできません。これは推測ですが、何が起きているのかを説明します。

残念ながら、SQLiteはウィンドウ関数などの機能をサポートしていません。だから、あなたが望むことをやることは、むしろ複雑で計算上の費用がかかります。これをアプリケーション層で行うほうが良いかもしれません。

+0

ありがとうございます。実際には、 'LIMIT'節を定数として構築しようとしているのは理にかなっています。私はソースコードを見てきましたが、正確な部分はまだ見つかりませんでした。私は、アプリケーションレイヤーでこれを行うことが可能性が高いことに同意します。本当に明白です。それが私が質問で明示的に言及しなかった理由です。私はこれをもっと知っている誰かが来るかどうか見るためにもう少し待つつもりです。もしそうでなければ、これは正しい長いコメントでしょう。 – simbabque

関連する問題