我正在编写一个带有排名算法的搜索例程,并希望一次性获得这个。
我的理想查询会是这样的......
select *, (select top 1 wordposition
from wordpositions
where recordid=items.pk_itemid and wordid=79588 and nextwordid=64502
) as WordPos,
case when WordPos<11 then 1 else case WordPos<50 then 2 else case WordPos<100 then 3 else 4 end end end end as rank
from items
是否可以在案例中使用WordPos?它在我身上产生错误,无效的列名称为“WordPos”。
我知道我可以为每个案例重做子查询,但我认为它实际上会重新运行案例不是吗?
例如:
select *, case when (select top 1 wordposition from wordpositions where recordid=items.pk_itemid and wordid=79588 and nextwordid=64502)<11 then 1 else case (select top 1 wordposition from wordpositions where recordid=items.pk_itemid and wordid=79588 and nextwordid=64502)<50 then 2 else case (select top 1 wordposition from wordpositions where recordid=items.pk_itemid and wordid=79588 and nextwordid=64502)<100 then 3 else 4 end end end end as rank from items
有效....但是每次真的重新运行相同的查询吗?
很难从测试中看出它第一次运行它很慢但后续运行很快......它正在缓存......所以这意味着它第一次运行第一行,后续运行三次从缓存中得到结果?
只是好奇最好的办法是...... 谢谢! 莱恩
答案 0 :(得分:1)
您可以使用子查询执行此操作。我会坚持使用您的SQL Server语法,即使问题标记为mysql:
select i.*,
(case when WordPos < 11 then 1
when WordPos < 50 then 2
when WordPos < 100 then 3
else 4
end) as rank
from (select i.*,
(select top 1 wpwordposition
from wordpositions wp
where recordid=i.pk_itemid and wordid=79588 and nextwordid=64502
) as WordPos
from items i
) i;
这也简化了case
语句。您不需要嵌套的case语句来处理多个条件,只需要多个where
子句。
答案 1 :(得分:0)
没有。输出子句中引入的标识符(它来自子查询的事实是无关紧要的)不能在同一个SELECT语句中使用。
以下是一些解决方案:
虽然“重写”每个案例的子查询非常混乱,但它仍然应该产生一个等效的计划 - 但查看查询配置文件! - 因为查询结果是非易失性的。因此,查询计划程序可以安全地移动等效的子查询,应将子查询/子查询移动到JOIN,以避免首先“重新运行”。 / p>
1 以下是使用JOIN的转换,这是我首选的方法。 (我发现,如果一个查询不能“轻松地”以JOIN方式编写,那么它可能会要求错误的东西或以其他方式显示架构设计的问题。)
select
wp.wordposition as WordPos,
case wp.wordposition .. as Rank
from items i
left join wordpositions wp
on wp.recordid = i.pk_itemid
where wp.wordid = 79588
and wp.nextwordid = 64502
我在这里假设了多样性(即wordid
是唯一的),应该对其进行验证。如果这种多样性无效且不可纠正(并且你确实使用的是SQL Server),那么我建议使用ROW_NUMBER()
和CTE。