并且我想在某个playerID之后选择下一行,其中state = 1并且如果在第一行开始播放器ID之后它找不到任何内容
预期结果:
playerID=8 => playerID 13
playerID=15 => playerID 8
现在我正在使用子查询和第二次查询,如果结果为null:
function getTargetID($killerID)
{
$result= $this->db->fetchSingle("
SELECT playerID FROM targets WHERE state=1 AND
ID>(SELECT ID FROM targets WHERE playerID=%u)
ORDER BY state DESC,ID LIMIT 1",$killerID);
if(!$result)
{
$result= $this->db->fetchSingle("
SELECT playerID FROM targets WHERE state=1 AND
ID>0 ORDER BY state DESC,ID LIMIT 1");
}
return $result;
}
但我认为这段代码非常丑陋且未经过优化
答案 0 :(得分:1)
SELECT playerID FROM targets
WHERE state=1
AND ID > (SELECT ID FROM targets
WHERE playerID=8)
ORDER BY ID ASC
LIMIT 1
答案 1 :(得分:1)
当然,这可以在一个查询中完成:
SELECT Origin.id,
COALESCE(MIN(CASE WHEN Targets.id > Origin.id
THEN Targets.playerId END), -- "after"
MIN(CASE WHEN Targets.id < Origin.id
THEN Targets.playerId END) -- "before"
) as nextPlayer
FROM Targets
JOIN (SELECT id, playerId
FROM Targets
WHERE playerId = %playerId) Origin
ON Origin.playerId <> Targets.playerId
WHERE state = 1
GROUP BY Origin.id
(genuine SQL Fiddle example!)
如果你得到一个空值,那就意味着没有一个有效的选择(“没人在这里,弹出!”)。
请注意,您的要求主要是扫描整个表/索引。虽然窗口函数LAG()
/ MIN()
和一个好的优化器可能会有所帮助,但我不确定我是否有一个很好的方法可以在任何 db中避免这种情况。哦,这个版本将安全地处理表中给定playerId
的多个实例。
除此之外,使用“桌子的顺序”是什么?这没有任何保证,并且显式创建了SQL来忽略这些事情(出于性能原因而被破坏,但概念就是这种情况)。
根据下一个顺序playerId
的要求,这是我之前提出的一个版本:
SELECT COALESCE(MIN(CASE WHEN playerId > %playerId
THEN playerId END), -- "after"
MIN(CASE WHEN playerId < %playerId
THEN playerId END) -- "before"
) as nextPlayer
FROM Targets
WHERE state = 1
答案 2 :(得分:1)
我建议使用嵌套选择:
select t.*,
coalesce((select playerID
from targets t2
where t2.state = t.state and
t2.id > t.id
order by t2.id
limit 1
),
(select PlayerId from targets t2 where t2.state = t.state order by id limit 1)
) as nextPlayerId
from targets t;
您应该在targets(state, id, PlayerId)
上建立索引。该索引应该将子查询减少为索引查找 - 关于解析此查询的最快方法。
答案 3 :(得分:0)
SELECT
*
FROM mytable
WHERE id > (
SELECT
ID
FROM mytable
WHERE player_id = 8
)
AND state = 1
ORDER BY ID ASC
LIMIT 1
或者
SELECT
MIN(id),
player_id,
state
FROM targets
WHERE state = 1
and id > (SELECT
ID
FROM targets
WHERE player_id = 8)