【问题标题】:Does a CASE statement lose alias scope in PostgreSQL?CASE 语句是否在 PostgreSQL 中失去别名范围?
【发布时间】:2015-04-27 21:43:01
【问题描述】:

首先,这条 SQL 有效:

select
    case
        when s.luserid > 0 then u.szusername
        when s.lgroupid > 0 then g.szgroup
        when s.lldapid > 0 then 'LDAP Group'
    end as name
from security s
left join users u on s.luserid = u.id
left join usergroups g on s.lgroupid = g.id
order by name

上面的代码块证明了别名 name 的排序有效,以及声明别名 name 有效,而术语 name 是保留字,与问题无关

我的问题发生在我使用别名的 case 语句时:

注意别名useid

select
    case
        when sa.luserid > 0 then sa.luserid
        when sa.lgroupid > 0 then sa.lgroupid
        when sa.lldapid > 0 then sa.lldapid
    end as useid,
from security s
left join users u on s.luserid = u.id
left join usergroups g on s.lgroupid = g.id
order by
        case
            when 'user selection' = 'all objects by user' then useid
            else s.lobjectid
        end

在运行 SQL 之前,文本 user selection 被解析器替换为文字文本。别名useids.lobjectid 都是bigint 类型。

when 'user selection' = 'all objects by user' then useid 处抛出错误。

我是否在 CASE 语句中丢失了别名 useid 的范围? 为什么我在这里尝试使用别名 useid 时会失败。

顺便说一句,这个 SQL 也可以:

select
    case
        when s.luserid > 0 then u.szusername
        when s.lgroupid > 0 then g.szgroup
        when s.lldapid > 0 then 'LDAP Group'
    end as name
from security s
left join users u on s.luserid = u.id
left join usergroups g on s.lgroupid = g.id
order by
        case
            when s.lobjectid > 0 then s.lobjectid
            else s.luserid
        end

上面的代码块证明了ORDER BY 语句中的CASE 语句确实有效。所有关于上述 SQL 块的逻辑操作的争论都与问题无关,因为它只是垃圾示例 SQL。

【问题讨论】:

  • 它们是不同的类型。为什么不只是 order by s.lobjectid, name ? (您不能按表达式 name 排序,因此您必须使用子选择或重复 case 表达式)
  • 如果您没有注意到,第一个 SQL 块可以正常工作,而不管 name 是否被保留。此外,这些只是示例。我已经更新了问题(特别是第二个 SQL 块,即失败的那个)以更匹配我的实际 SQL。对于之前存在的可怕示例 SQL,我感到非常抱歉。
  • 你说“我的问题发生在我做一个包含变量的case语句时:”变量在哪里?我什么都看不到。
  • @ypercube 变量是useid,我在select语句中定义了
  • 啊,那是别名,不是变量。无论如何,您不能在ORDER BYCASE 表达式中使用别名(如name)。您可以重复整个 case when s.luserid > 0 then u.szusername when s.lgroupid > 0 then g.szgroup when s.lldapid > 0 then 'LDAP Group' end 表达式或将整个表达式包装在子查询(派生表或 cte)中。

标签: sql postgresql sql-order-by


【解决方案1】:

您尝试做的事情在 Postgresql 中是不可能的,因为它不允许您在与字段相同的查询中使用 ALIAS。与Mysql不同,你可以做到。

要解决您的问题,您可以将查询创建为子查询,然后您的别名将成为一个字段,因此可以用作:

select useid, lobjectid from (
  select
      case
          when sa.luserid > 0 then sa.luserid
          when sa.lgroupid > 0 then sa.lgroupid
          when sa.lldapid > 0 then sa.lldapid
      end as useid,
      lobjectid
   from security s
  left join users u on s.luserid = u.id
  left join usergroups g on s.lgroupid = g.id
  ) as t
order by
        case
            when 'user selection' = 'all objects by user' then useid
            else lobjectid
        end

或者你可以重复整个案例块

  select
      case
          when sa.luserid > 0 then sa.luserid
          when sa.lgroupid > 0 then sa.lgroupid
          when sa.lldapid > 0 then sa.lldapid
      end as useid,
      lobjectid
   from security s
  left join users u on s.luserid = u.id
  left join usergroups g on s.lgroupid = g.id
order by
        case
            when 'user selection' = 'all objects by user' then 
                  case
                      when sa.luserid > 0 then sa.luserid
                      when sa.lgroupid > 0 then sa.lgroupid
                      when sa.lldapid > 0 then sa.lldapid
                  end
            else lobjectid
        end

有些引擎会让你使用 select 范围内的字段的订单号来排序:

select a, b, c from sometable order by 1, 2

这意味着此查询将按字段ab 排序

【讨论】:

    猜你喜欢
    • 2011-12-09
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多