我想为SQLite 3创建一个SQL查询,它获取满足特定条件的第一个值(最低ID)。如果没有这样的条目,我想得到一个随机的行。因此,假设表中至少有一个条目,我总是希望返回一行。
考虑这个示例表:
CREATE TABLE `jukebox` (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`title` TEXT NOT NULL,
`lastplayed` INTEGER NOT NULL DEFAULT '0'
);
对于此示例,我想要检索未播放的第一首歌曲( lastplayed = 0 )。如果没有这样的歌曲,我想从表格中随机返回一行。
这是我到目前为止创造的。这是一个丑陋的怪物,我很确定它不是很有效。
SELECT * FROM (
SELECT * FROM (SELECT * FROM jukebox WHERE lastplayed = 0 ORDER BY id DESC)
UNION
SELECT * FROM (SELECT * FROM jukebox ORDER BY RANDOM() LIMIT 1)
) LIMIT 1
我知道我可以省略ORDER BY id DESC
部分。我把它留在那里所以很清楚我期待的结果。
奇怪的是,我无法删除LIMIT 1
之后的RANDOM()
,因为我当时不会得到随机结果。
有没有办法优化此查询?
答案 0 :(得分:1)
您可以将您的版本表达为:
@property
或者,没有SELECT *
FROM ((SELECT * FROM jukebox WHERE lastplayed = 0 ORDER BY id DESC)
UNION ALL
(SELECT * FROM jukebox ORDER BY RANDOM() LIMIT 1)
)
)
ORDER BY lastplayed
LIMIT 1;
:
UNION ALL
但是,我认为这可能会更好:
SELECT *
FROM jukebox
ORDER BY (CASE WHEN lastplayed = 0 THEN 1 ELSE 2 END),
(CASE WHEN lastplayed = 0 THEN id END),
RANDOM()
LIMIT 1;
当第一个子查询已经匹配时,它应该避免排序。
答案 1 :(得分:1)
我认为CASE声明可以真正简化这个
(SELECT *
FROM jukebox
WHERE lastplayed = 0
ORDER BY id DESC
LIMIT 1
)
UNION ALL
(SELECT *
FROM jukebox
WHERE NOT EXISTS (SELECT 1 FROM jukebox WHERE lastplayed = 0)
ORDER BY RANDOM()
LIMIT 1
)