【问题标题】:postgres column alias problempostgres 列别名问题
【发布时间】:2010-12-11 08:43:24
【问题描述】:

作为 Postgresql 的新手(我要搬家是因为我要将我的网站转移到仅支持它的 heroku,我不得不重构我的一些查询和代码。这是一个我不太能解决的问题理解问题:

PGError: ERROR:  column "l_user_id" does not exist
LINE 1: ...t_id where l.user_id = 8 order by l2.geopoint_id, l_user_id ...
                                                             ^

...查询:

   select distinct 
          l2.*, 
          l.user_id as l_user_id, 
          l.geopoint_id as l_geopoint_id 
     from locations l 
left join locations l2 on l.geopoint_id = l2.geopoint_id 
    where l.user_id = 8 
 order by l2.geopoint_id, l_user_id = l2.user_id desc

添加了子句“l.user_id as l_user_id, l.geopoint_id as l_geopoint_id”,因为显然 postgres 不喜欢未选择字段的 order 子句。但是我现在得到的错误使它看起来我也没有得到别名。有 postgres 经验的人看到这个问题吗?

我可能会遇到很多这样的问题——查询在 mySql 中运行良好...

【问题讨论】:

  • 越容易阅读,我们就越容易为您提供帮助...

标签: sql mysql postgresql alias heroku


【解决方案1】:

在 PostgreSQL 中,您不能使用带有别名的表达式按顺序排列。只有普通别名在那里工作。您的查询应如下所示:

   select distinct 
          l2.*, 
          l.user_id as l_user_id, 
          l.geopoint_id as l_geopoint_id 
     from locations l 
left join locations l2 on l.geopoint_id = l2.geopoint_id 
    where l.user_id = 8 
 order by l2.geopoint_id, l.user_id = l2.user_id desc;

我假设你的意思是 l2.user_id=l.user_id 应该先走。

This is relevant message 在 PostgreSQL 通用邮件列表中。以下在documentation of ORDER BY clause

每个表达式可以是名称或 输出的序数 列(选择列表项),或者它 可以是一个任意的表达式 来自输入列值。

所以在使用表达式时没有别名。

【讨论】:

  • 好的——根据规则,这是有道理的,但对于多年来一直使用 mySql 的人来说,这并不完全直观。我会在代码中尝试...
【解决方案2】:

我在使用来自fuzzystrmatch 的函数时遇到了同样的问题——尤其是levenshtein 函数。我需要按字符串距离排序,并按字符串距离过滤结果。我最初是在尝试:

SELECT thing.*, 
levenshtein(thing.name, '%s') AS dist 
FROM thing 
WHERE dist < character_length(thing.name)/2 
ORDER BY dist

但是,当然,我从 WHERE 子句中得到了错误“列”dist“不存在”。我试过了,它奏效了:

SELECT thing.*, 
(levenshtein(thing.name, '%s')) AS dist 
FROM thing 
ORDER BY dist

但我需要在 WHERE 子句中具有该限定条件。这个问题中的其他人说,在 ORDER BY 之前评估了 WHERE 子句,因此在评估 WHERE 子句时该列不存在。按照这个建议,我发现嵌套的 SELECT 语句可以解决问题:

SELECT * FROM 
(SELECT thing.*, 
     (levenshtein(thing.name, '%s')) AS dist 
     FROM thing 
     ORDER BY dist
) items 
WHERE dist < (character_length(items.name)/2)

请注意,“items”表别名是必需的,并且 dist 列别名可在外部 SELECT 中访问,因为它在语句中是唯一的。这有点时髦,我很惊讶在 PG 中它必须是这种方式 - 但它似乎没有受到性能影响,所以我很满意。

【讨论】:

  • 请注意,没有保证子查询中的 ORDER BY 子句将导致最终结果按该顺序排列,尽管我不知道这个特定查询否则会做的任何优化。不过,将 ORDER BY 子句移出显式影响最终结果的子查询会更安全。
  • @kgrittn。感谢您的指针,但是,当它通过在子查询中给出 order by 子句对我有用时。如果有任何特定情况,请提供信息。
  • @kartik-narayana-maringanti 它可能每次现在都会按预期工作-问题是您是否要将其保留在新版本可能会中断的状态排序,或者以保证现在和未来版本都有效的形式编写它。如果您可以依靠未记录的实现细节而不是记录的方法,那么您很好。
【解决方案3】:

你有:

order by l2.geopoint_id, l_user_id = l2.user_id desc

在您的查询中。那是非法的语法。删除 = l2.user_id 部分(如果这是连接条件之一,请将其移至 where),它应该可以工作。

更新下面的选择(删除= l2.user_id)应该可以正常工作。我已经在 Postgres 8.3 上测试过它(显然使用不同的表/列名)

select distinct 
       l2.*, 
       l.user_id as l_user_id, 
       l.geopoint_id as l_geopoint_id 
  from locations l 
  left join locations l2 on l.geopoint_id = l2.geopoint_id 
 where l.user_id = 8 
 order by l2.geopoint_id, l_user_id desc

【讨论】:

  • 我将引用更改为非别名引用,一切都很好。但是,对您建议的更改并没有改变别名问题:它仍然不喜欢 l_user_id 别名...
  • 这不等同于有问题的查询。 “order by l_user_id = l2.user_id desc”表示 l.user_id 和 l2.user_id 相等的行必须先行。
【解决方案4】:

“被添加是因为 postgres 显然不喜欢未选择字段的 order 子句”

“就 order by 而言 - 是的,PostgresQL(和许多其他数据库)不允许按未在 select 子句中列出的列进行排序。”

完全不真实。

=> SELECT id FROM t1 ORDER BY owner LIMIT 5;

身份证

30 10 20 50 40 (5 行)

【讨论】:

    猜你喜欢
    • 2019-06-20
    • 2021-05-27
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 2011-04-30
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多