繁体   English   中英

Postgres中的优先选择语句

[英]Priority select statement in Postgres

我有Rails应用程序。 在此应用程序中,我将模块globalize3用于i18n。 我有带有此行的localedescriptiontitle表格newsnews_translations 我使用join语句获取所有新闻检查当前区域设置。 对于当前语言环境,这是正确的工作。 例如:

WHERE "news_tranlations"."locale" = 'it'

但我想提出另一种逻辑。 例如,如果来自'de'用户,我向他显示所有带有语言环境'de'新闻,以及所有没有'de'翻译但带有'en' 当我尝试使用OR语句执行此操作时,我得到两个翻译为'de''en' 我是否可以使用优先级之类的东西来纠正问题。

这是一个尴尬的查询。 简而言之,您需要对可能的行进行“或”运算,然后计算case when locale = 'it' then 1 when ... endcase when locale = 'it' then 1 when ... end排序的子结果集的顶行, case when locale = 'it' then 1 when ... end排序。 有很多方法可以得出正确的结果(尤其是窗口函数),但是坦率地说,出于性能方面的考虑,您真的不想去那里。

Methinks重新审视您的假设,或更改您的架构。

使它相当快的一种方法是将数组列添加到由触发器维护的新闻项(例如languages )中。 使用该新闻过滤热门新闻(我认为这是您要获取的新闻),而不是针对翻译进行联接。 (注意:根据您的Postgres版本,请避免在该列上添加GIST索引,因为&&运算符的选择性是硬编码的,并且会使用超出特定行的btree超过/ by / limit / offset的顺序。)

使其变得相当快的另一种方法是跟踪每种语言的单独的供稿表-基本上是一个物化视图,该视图产生您要构建的查询的ID。

如您所见,这两种选择都等于部分或完全预先计算了每种语言所显示的行。 根据我自己的经验,使用数组列的第一种方法可以很好地工作-我喜欢将其用于标签,加快和/或过滤。

认真考虑Denis关于性能和更改架构的评论。 但是,以下内容确实可以解决您的问题,并且如果您不让weighted_tables变得太大,则可能适用。 请特别注意,公用表表达式(表WITH生成的表)上没有索引。

SQL小提琴

您可以使用DISTINCT和ORDER BY来欺骗它。

我不知道您的新闻主键和外键是什么,但是假设它是“ news_id”,则可以这样操作:

SELECT
  DISTINCT ON (n.news_id),
  n.news_id,
  nt.title,
  nt.description
FROM
  news n INNER JOIN news_translation nt
ON
  n.news_id = nt.news_id
ORDER BY
  n.news_id,
  nt.locale != 'de',
  nt.locale != 'en',
  nt.locale;

该查询将始终向您返回新闻文章一次(没有重复和多次翻译),并且最好为您提供“ de”翻译(如果存在),如果不存在,它将归为“ en”,如果两者均不包含存在,它将为您提供按“语言环境”排序的第一个翻译。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM