在SQLite中,可以使用任何返回或可以转换为整数的表达式作为LIMIT
的参数。
任何标量表达式都可以在LIMIT子句中使用,只要它计算为整数或可以无损转换为整数的值即可。 [...]
这意味着,以下是可能的(我将在下面显示用于此的数据库):
SELECT * FROM event_attendees
WHERE dtime IS NULL
ORDER BY rtime ASC
LIMIT (
SELECT max_participants FROM `events` WHERE id = 1
);
此查询将运行并返回结果。
但是,我试图在子查询中使用它,但这给了我一个错误消息。
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运行它时,错误信息是:
在数据库'foo'上执行SQL查询时出错:没有这样的列events.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
s。
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
列。
我错过了什么,或者这是不可能的,因为我不知道有些限制?还有另一种方法吗?
答案 0 :(得分: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
需要是一个常量,但它会从一行变为另一行。
似乎SQLite将此扩展为禁止相关子查询。我不完全理解SQLite的内部。我可以想象在解析和执行LIMIT
查询之前解析并执行SELECT
子句。因此,它无法使用外部查询中的表。这是推测,但它可以解释正在发生的事情。
不幸的是,SQLite不支持窗口功能或类似功能。所以,做你想做的事情是相当复杂和计算上昂贵的。你可能最好在应用层做这件事。