将这样的表视为一个非常简单的例子:
|----------------------------------|
| names |
|----------------------------------|
| id | name_id | name | language |
|----------------------------------|
| 1 | 1 | foo | en |
|----------------------------------|
| 2 | 1 | foose | fr |
|----------------------------------|
我希望得到名称为'foo'且语言为'fr'的行,但如果没有语言'fr'的行,则回退到语言为'en'的行。所以我的第一个想法就是写一个这样的查询:
SELECT *
FROM names
WHERE name ILIKE '%foo%' AND (language = 'fr' OR language = 'en')
只要只有一种语言可用,这样就可以正常工作,但当两种语言都可用时,它会返回两行,所以我添加了一个DISTINCT ON:
SELECT DISTINCT ON (name_id) *
FROM names
WHERE name ILIKE '%foo%' AND (language = 'fr' OR language = 'en')
但是这个不起作用,因为它返回语言为'en'的那个。
有什么想法吗?
答案 0 :(得分:1)
就像你用你的第一个查询做的那样,只是选择排序的前一个查询" fr"来之前" en"。
SELECT *
FROM names
WHERE name LIKE '%foo%' AND (language = 'fr' OR language = 'en')
ORDER BY language DESC
LIMIT 1
答案 1 :(得分:1)
with s as (
select *
from names
where
name ilike '%foo%'
and
language in ('fr', 'en')
), fr as (
select *
from s
where language = 'fr'
), en as (
select *
from s
where language = 'en'
)
select *
from fr
union all
select *
from en
where (select count(*) from fr) = 0
如果法语行数为零,它只会添加英文行。
答案 2 :(得分:0)
这是我最后的实施,它依赖于@Amadan的评论,所以对他赞不绝口。 @Clodoaldo Neto方法也适用,但这个对我来说更简单。
SELECT DISTINCT ON (name_id) *
FROM names
WHERE name ILIKE '%foo%' AND language IN ('en', 'fr')
ORDER BY name_id, language = 'fr' DESC
最后一个提示,如果语言可以为空(就像在我的情况下一样),条件应该合并,因为它将返回置于顶部的空值:
SELECT DISTINCT ON (name_id) *
FROM names
WHERE name ILIKE '%foo%' AND language IN ('en', 'fr')
ORDER BY name_id, COALESCE(language = 'fr', FALSE) DESC