【问题标题】:Merge two columns based on a table value根据表值合并两列
【发布时间】:2017-05-28 06:20:03
【问题描述】:

我正在尝试将法语字符串(语言 ID 1)合并为一列。到目前为止,我能够在table1.titletable2.translated_topic 中获得法语字符串,但不知道如何连接它们。

版本:Postgres 9.6.0

源表架构:

表一:knowledgebase_topics

id | title            | language_id |
------------------------------------
64   | The Topic      |    91       |  
65   | The Topic 2    |    91       |           
62   | Le fav sujet   |     1       |          
63   | Le fav sujet 2 |     1       |          
61   | le bonjour     |     1       |     

表2:knowledgebase_topics_translations

id | translated_topic| knowledgebase_topic_id | language_id |
-------------------------------------------------------------
   | Le sujet        |          64            |     1       | 
   | Le sujet 2      |          65            |     1       |
   | Fav The Topic   |          62            |     91      |
   | Fav The Topic 2 |          63            |     91      |

给定以下查询:

SELECT title, translated_topic, "kbt".language_id, "kbtt".language_id
FROM knowledgebase_topics as "kbt" 
LEFT JOIN knowledgebase_topics_translations as "kbtt" on ("kbtt".knowledgebase_topic_id = "kbt".id) 
INNER JOIN knowledgebase_topics_organizations as "kbto" on ("kbto".knowledgebase_topic_id = "kbt".id) 
WHERE "kbto"."organization_id" = 1 
AND to_tsvector("kbt".title) @@ to_tsquery('le') 
OR to_tsvector("kbtt".translated_topic) @@ to_tsquery('le') 
AND "kbt".language_id = 1 
OR "kbtt".language_id = 1;

我得到以下结果:

     title      | translated_topic | language_id | language_id 
----------------+------------------+-------------+-------------
 The Topic      | Le sujet         |          91 |           1
 The Topic 2    | Le sujet 2       |          91 |           1
 Le fav sujet   | Fav The Topic    |           1 |          91
 Le fav sujet 2 | Fav The Topic 2  |           1 |          91
 le bonjour     |                  |           1 |     

所需结果: table1.titletable2.translated_topics 已基于 language_id == 1 合并。两个表都有一个语言 ID 列。

     title      | language_id
----------------+--------------
 Le sujet       | 1
 Le sujet 2     | 1
 Le fav sujet   | 1
 Le fav sujet 2 | 1
 le bonjour     | 1

我该怎么做?


注意:我不想简单地检查 lang IDs = 1,比如

and "kbt".language_id = 1 AND (instead of OR) "kbtt".language_id = 1;

因为这会导致语言 ID 为 1 的 table 2 中的 2 条记录丢失:

     title      | translated_topic | language_id | language_id 
----------------+------------------+-------------+-------------
 Le fav sujet   | Fav The Topic    |           1 |          91
 Le fav sujet 2 | Fav The Topic 2  |           1 |          91
 le bonjour     |                  |           1 |          

所以,我已经让它工作了……但这性能好吗?

SELECT title, "kbt".language_id
FROM knowledgebase_topics as "kbt" 
INNER JOIN knowledgebase_topics_organizations as "kbto" on ("kbto".knowledgebase_topic_id = "kbt".id) 
WHERE "kbto"."organization_id" = 1
AND to_tsvector("kbt".title) @@ to_tsquery('le') 
AND "kbt".language_id = 1 
UNION ALL
SELECT translated_topic, "kbtt".language_id 
FROM knowledgebase_topics_translations as "kbtt"
INNER JOIN knowledgebase_topics_organizations as "kbto" on ("kbto".knowledgebase_topic_id = "kbtt".id) 
WHERE "kbto"."organization_id" = 1
AND to_tsvector("kbtt".translated_topic) @@ to_tsquery('le')
AND "kbtt".language_id = 1;

给出输出:

     title      | language_id 
----------------+-------------
 le bonjour     |           1
 Le fav sujet   |           1
 Le fav sujet 2 |           1
 Le sujet       |           1
 Le sujet 2     |           1
(5 rows)

【问题讨论】:

  • 所以你想要一个只有 'language_id' 1 的结果集?或者一个结果集只有 'language_id' 1 连接的行,而其他值没有?
  • 我想要来自 table1.titletable2.translated_topic 的所有行,其 language_id == 1,并满足其他约束 (tsvector, tsquery, org ID match, etc). I'd like the result sets in a single column like merged`
  • @MeesKluivers 澄清见上文
  • @MeesKluivers @MeesKluivers 见上文进行澄清。基本上我想合并两个表列的结果,其中language_id = 1.
  • 也许你应该看看 CASE。类似于 CASE WHEN kbt.langid = 1 AND kbtt.langid = 1 THEN .. 等postgresql.org/docs/7.4/static/functions-conditional.html

标签: postgresql join merge union


【解决方案1】:

设置环境来回答问题

首先,观察我们如何用简洁的 DDL 最好地描述问题。最好在将来,您将学习如何编写这样的问题..

CREATE TEMPORARY TABLE knowledgebase_topics AS
SELECT * FROM ( VALUES
  (64,'The Topic',91),
  (65,'The Topic 2',91),
  (62,'Le fav sujet',1),
  (63,'Le fav sujet 2',1),
  (61,'le bonjour',1)
) AS t(knowledgebase_topic_id, title, language_id);

CREATE TEMPORARY TABLE knowledgebase_topics_translations AS
SELECT * FROM ( VALUES
  ('Le sujet'       ,64,1  ),
  ('Le sujet 2'     ,65,1  ),
  ('Fav The Topic'  ,62,91 ),
  ('Fav The Topic 2',63,91 )
) AS t(translated_topic, knowledgebase_topic_id, language_id);

那么您只需告诉我们您想要什么,我们就可以轻松搭建工作环境并回答您的问题。不需要英语!对我们俩都更轻松。

解决办法

在这里,我们使用UNION ALL 将其包装在SELECT 中,以便我们可以按ID 排序,并在一个位置轻松更改您要查找的language

SELECT title, language_id
FROM (
  SELECT knowledgebase_topic_id, title, language_id
  FROM knowledgebase_topics
  UNION ALL
  SELECT knowledgebase_topic_id, translated_topic, language_id
  FROM knowledgebase_topics_translations
) AS t(id, title, language_id)
WHERE language_id = 1
ORDER BY id;

输出

     title      │ language_id 
────────────────┼─────────────
 le bonjour     │           1
 Le fav sujet   │           1
 Le fav sujet 2 │           1
 Le sujet       │           1
 Le sujet 2     │           1
(5 rows)

【讨论】:

  • @Growler 我会亲自架构更改这一点。我会选择一种主要语言——出于第三方工具的目的,您确实也有一种索引语言。然后,如果它们没有被索引,我会将翻译放在 JSONB 中。或者,我会根据它们的名称和翻译将它们放在单独的列中。CREATE TABLE movie_table ( id serial PRIMARY KEY, name text, fr text );。等我不会加入时尚。您有一个主表和一个辅助表。我不确定为什么。你想像他们一样查询他们告诉我你也不知道为什么。
  • 埃文,您通过提供问题的答案和编写更好问题的示例来帮助我(希望还有其他人)超越自我。非常感谢!
  • 您可能还想尝试 dba.stackexchange.com,如果您想获取有关性能等的信息。当您需要查询时,请始终提供 DDL 以生成查询(CREATE TABLE AS SELECT),或者如果您需要性能建议(始终提出另一个问题)并粘贴查询,并输出 EXPLAIN ANALYZE
  • Evan 在您选择的第一个表中没有knowledgebase_topic_idknowledgebase_topics。你可能想把它改成id
  • 还有organization_id的检查应该存在于哪里?
猜你喜欢
  • 2013-06-07
  • 2021-09-17
  • 1970-01-01
  • 1970-01-01
  • 2013-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多