SQL: UNION таблицы и избежать дублирования ключей - PullRequest
0 голосов
/ 05 ноября 2019

Я пытаюсь объединить 2 таблицы, но избегаю дублирования строк по заданному ключу (id). В случае дублированного идентификатора следует выбрать строку из таблицы B.

SELECT * FROM A UNION ALL SELECT * FROM TABLE B

Приведенный выше запрос просто объединит все строки, но я пытаюсь добиться результата, показанного ниже.

Таблица A

+----+------+---+
| id | name | p |
+----+------+---+
|  1 | abc  | A |
|  2 | bcd  | A |
|  3 | cde  | A |
+----+------+---+

Таблица B

+----+------+---+
| id | name | p |
+----+------+---+
|  3 | ccc  | A |
|  4 | ddd  | A |
|  5 | eee  | A |
+----+------+---+

Результат

+----+------+---+
| id | name | p |
+----+------+---+
|  1 | abc  | A |
|  2 | bcd  | A |
|  3 | ccc  | A |
|  4 | ddd  | A |
|  5 | eee  | A |
+----+------+---+

Ответы [ 3 ]

2 голосов
/ 05 ноября 2019

Я думаю, что вы хотите запрос расстановки приоритетов - выберите все из b, а затем несовпадающие строки из a:

select b.id, b.name, b.p
from b
union all
select a.id, a.name, a.p
from a
where not exists (select 1 from b where b.id = a.id);
0 голосов
/ 05 ноября 2019

Вот что я использовал

Идея состоит в том, чтобы создать Псевдоколонку , которая будет ==> NULL для Таблица A и будетиметь ==> name из таблицы B и затем выбрать ненулевое значение в качестве final_name

Sql Выполнено:

 val resultSql = """ select sub.id, 
                            sub.p, 
                             max(nvl(sub.pseudo_name,sub.name)) as result_name 
                              from 
                             (
                               select a.id,
                                      a.name, 
                                      a.p, 
                                      null  as pseudo_name from a 
                             union all 
                               select b.id,
                                      b.name,
                                      b.p, 
                                      b.name as pseudo_name  from b ) sub 
                     group by 1,2 order by 1"""

Полный код =>

val table1 = Seq((1,"abc","A"),(2,"bcd","A"),(3,"first_table_value","A")).toDF("id","name","p")
val table2 = Seq((3,"second_table_value","A"),(4,"ddd","A"),(5,"eee","A")).toDF("id","name","p")
table1.createOrReplaceTempView("A")
table2.createOrReplaceTempView("B")
val resultSql = """ select sub.id, sub.p, max(nvl(sub.pseudo_name,sub.name)) as result_name from (select a.id,a.name, a.p, null  as pseudo_name from a union all  select b.id, b.name,b.p, b.name as pseudo_name  from b ) sub group by 1,2 order by 1"""
spark.sql(resultSql).show(false)

И ВЫХОД =>

|id |p  |result_name       |
+---+---+------------------+
|1  |A  |abc               |
|2  |A  |bcd               |
|3  |A  |second_table_value|
|4  |A  |ddd               |
|5  |A  |eee               |
+---+---+------------------+
0 голосов
/ 05 ноября 2019

Я бы попробовал это, поскольку вы не можете полагаться на значения p:

WITH                                                                                                                                                    
-- your input starts here
a(id,name,p) AS (
          SELECT 1,'abc','A'
UNION ALL SELECT 2,'bcd','A'
UNION ALL SELECT 3,'cde','A'
)
,
b(id,name,p) AS (
          SELECT 3,'ccc','A'
UNION ALL SELECT 4,'ddd','A'
UNION ALL SELECT 5,'eee','A'
)
-- your input ends here
-- replace the comma below with "WITH"
,
combi AS (
SELECT
  1 AS tb_priority
, *
FROM a
UNION ALL
SELECT
  2 AS tb_priority
, *
FROM b
)
SELECT
  id
, name
, p
FROM combi u
WHERE tb_priority = (
  SELECT MAX(tb_priority)
  FROM combi c
  WHERE c.id = u.id
)
;                                                                                                                                                       

  id | name | p 
 ----+------+---
   1 | abc  | A
   4 | ddd  | A
   2 | bcd  | A
   5 | eee  | A
   3 | ccc  | A
...