SQL查询优化:带有特定条件的条目,或者随机输入

时间:2015-08-08 14:47:16

标签: sql sqlite

我想为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(),因为我当时不会得到随机结果。

有没有办法优化此查询?

2 个答案:

答案 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
)