是否可以在同一外部查询的case语句中使用子查询的结果?

时间:2013-11-01 22:22:59

标签: sql tsql

我正在编写一个带有排名算法的搜索例程,并希望一次性获得这个。

我的理想查询会是这样的......

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 

有效....但是每次真的重新运行相同的查询吗?

很难从测试中看出它第一次运行它很慢但后续运行很快......它正在缓存......所以这意味着它第一次运行第一行,后续运行三次从缓存中得到结果?

只是好奇最好的办法是...... 谢谢! 莱恩

2 个答案:

答案 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语句中使用。

以下是一些解决方案:

  1. 使用JOIN 1 重写查询,这将完全消除问题并与RA完全吻合。
  2. 将带有子查询的整个SELECT包装在另一个带有大小写的SELECT中。 外部选择可以访问内部SELECT的输出子句引入的标识符。
  3. 使用CTE(如果是SQL Server)。这类似于#2,因为它允许引入标识符。
  4. 虽然“重写”每个案例的子查询非常混乱,但它仍然应该产生一个等效的计划 - 但查看查询配置文件! - 因为查询结果是非易失性的。因此,查询计划程序可以安全地移动等效的子查询,将子查询/子查询移动到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。