CASE 语句是否会在 PostgreSQL 中丢失别名作用域?
Does a CASE statement lose alias scope in PostgreSQL?
首先,这个 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
被解析器替换为文字文本。别名 useid
和 s.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。
您尝试执行的操作在 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
这意味着此查询将按字段 a
和 b
排序
首先,这个 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
被解析器替换为文字文本。别名 useid
和 s.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。
您尝试执行的操作在 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
这意味着此查询将按字段 a
和 b