提取特定或其他语言的页面数据

时间:2019-08-11 18:32:49

标签: sql sqlite

我有一个包含网页数据的表格,看起来像这样:

row_id  ⁞ page_id ⁞ lang ⁞ title              ⁞ slug
────────┼─────────┼──────┼────────────────────┼────────────────
1       ⁞1        ⁞ en   ⁞ Welcome!           ⁞ begin
2       ⁞1        ⁞ fr   ⁞ Bienvenue!         ⁞ bienvenue
3       ⁞2        ⁞ pl   ⁞ Podstrona          ⁞ podstrona
4       ⁞2        ⁞ en   ⁞ Subpage            ⁞ subpage
5       ⁞3        ⁞ pl   ⁞ Podstrona 2        ⁞ podstrona-2
6       ⁞4        ⁞ fr   ⁞ Coordonnées        ⁞ coordonnees
7       ⁞5        ⁞ pl   ⁞ Podstrona poziom 2 ⁞ podstrona-lvl-2
8       ⁞5        ⁞ en   ⁞ Subpage Lvl 2      ⁞ subpage-lvl-2
9       ⁞6        ⁞ pl   ⁞ Poziom 3           ⁞ poziom-3
10      ⁞6        ⁞ en   ⁞ Level 3            ⁞ lvl-3
11      ⁞7        ⁞ pl   ⁞ Błąd 404           ⁞ 404
12      ⁞7        ⁞ en   ⁞ Error 404          ⁞ 404
13      ⁞7        ⁞ fr   ⁞ Erreur 404         ⁞ 404

我想按优先顺序获取每个页面的单一语言版本。假设我想获取所有 fr 语言的页面,但是如果某些页面缺少该语言版本,则改为获取 en 版本,但是如果没有< em> en ,尝试 pl ,依此类推;因此在这种情况下,结果将如下所示:

row_id  ⁞ page_id ⁞ lang ⁞ title              ⁞ slug
────────┼─────────┼──────┼────────────────────┼────────────────
2       ⁞1        ⁞ fr   ⁞ Bienvenue!         ⁞ bienvenue
4       ⁞2        ⁞ en   ⁞ Subpage            ⁞ subpage
5       ⁞3        ⁞ pl   ⁞ Podstrona 2        ⁞ podstrona-2
6       ⁞4        ⁞ fr   ⁞ Coordonnées        ⁞ coordonnees
8       ⁞5        ⁞ en   ⁞ Subpage Lvl 2      ⁞ subpage-lvl-2
10      ⁞6        ⁞ en   ⁞ Level 3            ⁞ lvl-3
13      ⁞7        ⁞ fr   ⁞ Erreur 404         ⁞ 404

语言数量没有预先定义,但是每页必须至少具有一种语言版本。

可以处理大量查询,或者获取所有数据,然后通过PHP进行编程处理,但是我想知道是否有一种优雅的SQL(SQLite)解决方案可以在一个查询中解决这个问题? / p>

2 个答案:

答案 0 :(得分:2)

有条件聚合:

select t.* 
from (
  select 
    page_id,
    max(lang ='fr') fr,
    max(lang ='en') en,
    max(lang ='pl') pl
  from tablename
  group by page_id
) g inner join tablename t
on t.page_id = g.page_id
and t.lang = case 1
  when g.fr then 'fr' 
  when g.en then 'en'
  when g.pl then 'pl'
end

请参见demo

或者,如果您的SQLite版本允许使用窗口函数:

with 
  cte(id, lang) as (
    select * from 
    (values (1, 'fr'), (2, 'en'), (3, 'pl')) 
  ),
  langs as (   
    select t.*,
      row_number() over (partition by t.page_id order by c.id) rn
    from cte c inner join tablename t
    on t.lang = c.lang
  )  
select row_id, page_id, lang, title, slug 
from langs  
where rn = 1
order by page_id 

请参见demo

结果:

| row_id | page_id | lang | title         | slug          |
| ------ | ------- | ---- | ------------- | ------------- |
| 2      | 1       | fr   | Bienvenue!    | bienvenue     |
| 4      | 2       | en   | Subpage       | subpage       |
| 5      | 3       | pl   | Podstrona 2   | podstrona-2   |
| 6      | 4       | fr   | Coordonnées   | coordonnees   |
| 8      | 5       | en   | Subpage Lvl 2 | subpage-lvl-2 |
| 10     | 6       | en   | Level 3       | lvl-3         |
| 13     | 7       | fr   | Erreur 404    | 404           |

答案 1 :(得分:2)

这是一种优先级查询。我只会在case中使用row_number()表达式:

select t.*
from (select t.*,
             row_number() over (case lang when 'fr' then 1 when 'en' then 2 when 'pl' then 3 else 4 end) as seqnum
      from t
     ) t
where seqnum = 1;

在旧版本的SQLite中,您可以使用聚合和coalesce()

select page_id,
       coalesce( max(case when lang = 'fr' then title end),
                 max(case when lang = 'en' then title end),
                 max(case when lang = 'po' then title end),
                 max(title)  -- catchall for everything else
               ) as title,
       coalesce( max(case when slug = 'fr' then title end),
                 max(case when slug = 'en' then title end),
                 max(case when slug = 'po' then title end),
                 max(slug)  -- catchall for everything else
               ) as slug
from t
group by page_id;

或者,使用相关子查询:

select t.*
from t
where t.lang = (select t2.lang
                from t t2
                where t2.page_id = t.page_id
                order by (case t2.lang when 'fr' then 1 when 'en' then 2 when 'po' then 3 else 4 end)
                limit 1
               ) ;