在SQL中,为什么这个JOIN会两次返回键列?

时间:2017-07-25 19:18:57

标签: sql pyspark-sql

对不起,如果这是一个愚蠢的问题,但我似乎无法理解它。我对SQL很新,这种行为在R或Pandas或我曾经使用过的其他东西中会很奇怪。

基本上,我在两个不同的数据库中有两个表,共有一个密钥user_id。我想用

加入所有列
SELECT * FROM db1.first_table t1 
JOIN db2.second_table t2 
ON t1.user_id = t2.user_id

很好,它有效。除了有两个(相同的)列称为user_id。这并不重要,除了我在pyspark中这样做,当我尝试将连接表导出到平面文件时,我得到一个错误,其中两列具有相同的名称。有一些解决方法,但我想知道是否有人可以解释为什么连接返回两个 user_id列。看起来它是一个内连接,所以根据定义,列是相同的。为什么会同时返回?

作为一个附带问题,是否有一种简单的方法可以避免这种行为?

提前致谢!

5 个答案:

答案 0 :(得分:2)

所有这些答案(OP自己写的答案除外)似乎都假定我们在非常小的表上进行操作,可以在其中手动键入所需的每一列。

PySpark中最简单的解决方案是使用DataFrame连接语法:

Object.const_get(c)

这不会重复该列,其行为类似于熊猫合并。如果没有特殊原因必须将其编写为sql命令,则建议这样做。将此与

对比
df = left_df.join(right_df, ["name"])

行为类似于SQL连接并保留两列!

这也适用于Scala和R see here

另一种解决方案是将第二个目标列重命名为“ target_dataframe2”,然后与sql联接,然后再次简单地删除“ target_dataframe2”。

答案 1 :(得分:1)

SELECT *返回查询的所有表中的所有列。这包括user_id列 - 一个来自表A,一个来自表B.

最佳做法是列出您想要专门返回的列名称,但缩短列表的另一个选项是:

SELECT TableA.*, 
       TableB.col1, 
       TableB.col2, 
       ...rest of B columns except user_id

答案 2 :(得分:1)

您可以减少引用所需字段的字段数。

现在你有

  SELECT *

等于

  SELECT t1.*, t2.*

也许你想要像

这样的东西
  SELECT t1.*, t2.field1, t2.field2 ...

答案 3 :(得分:1)

好的,我想办法在不输入所有列名的情况下这样做(正如我在评论中提到的那样,总共有~5k列)。

这是pyspark特有的,但我只是将列名导出到csv并加载它们并执行以下操作:

with open("t1_cols.csv") as data_file:    
    t1_cols = data_file.read().split('\n')
with open("t2_cols.csv") as data_file:    
    t2_cols = data_file.read().split('\n')

sql = 'SELECT t1.user_id, t1.' + ', t1.'.join(t1_cols) + \
', t2.' + ', t2.'.join(t2_cols) + ' ' + \
'FROM db1.first_table t1 JOIN db2.second_table t2 ON t1.user_id = t2.user_id'

df = sqlContext.sql(sql)

有点讨厌,但它奏效了。

另外,我接受了第一个答案,因为所有上述答案在技术上都是正确的,这是第一个答案。谢谢你的帮助!

答案 4 :(得分:0)

这是因为您使用的是Select *。仅在*之后定义SELECT时,它将返回两个表中的所有列。你必须定义列名。始终定义要显示的列。你可以这样做:

SELECT t1.userid, t1.ColumnName1, t2.ColumnName2
FROM db1.first_table t1 
INNER JOIN db2.second_table t2 ON t1.user_id = t2.user_id

*可以通过以下方式使用:

以下查询将返回两个表中的所有列:

SELECT *
FROM db1.first_table t1 
INNER JOIN db2.second_table t2 ON t1.user_id = t2.user_id

以下查询将返回first_table表中的所有列:

SELECT t1.*
FROM db1.first_table t1 
INNER JOIN db2.second_table t2 ON t1.user_id = t2.user_id

以下查询将返回Second_table表中的所有列:

SELECT t2.*
FROM db1.first_table t1 
INNER JOIN db2.second_table t2 ON t1.user_id = t2.user_id

此外,您可以通过以下方式从一个表和其他表中的某些列获取所有列:

SELECT t1.*, t2.ColumnName
FROM db1.first_table t1 
INNER JOIN db2.second_table t2 ON t1.user_id = t2.user_id