Различные типы соединения таблиц в PySpark SQL

В этой статье мы рассмотрим различные типы соединений (JOIN), которые предлагает PySpark SQL, с их синтаксисом и простыми примерами.

Различные типы соединений (JOIN)
Image by educba

Список соединений, предоставляемых PySpark SQL, следующий:

  • INNER JOIN или просто JOIN – внутреннее соединение
  • LEFT OUTER JOIN – левое внешнее соединение
  • RIGHT OUTER JOIN – правое внешнее соединение
  • OUTER / FULL JOIN – полное внешнее соединение
  • CROSS JOIN – перекрестное (или декартово) произведение
  • LEFT ANTI JOIN – левое антисоединение
  • LEFT SEMI JOIN – левое полусоединение
  • SELF JOIN – соединение внутри одной таблицы

БЕСПЛАТНО СКАЧАТЬ КНИГИ в телеграм канале "Библиотека тестировщика"

INNER JOIN

Возвращает только те строки из обоих фреймов данных (dataframes), которые имеют совпадающие значения в обоих столбцах, указанных в качестве ключей объединения.

Синтаксис

df1.join(df2, df1['key'] == df2['key'], 'inner').show()

В приведенном выше примере  df1 и df2 – это два объединяемых фрейма данных, а key – это столбец, который используется в качестве ключа объединения. Последний параметр,  'inner', задает тип соединения, которое должно быть выполнено.

Пример

from pyspark.sql import SparkSession

# Create a Spark session
spark = SparkSession.builder.appName("InnerJoinExample").getOrCreate()

# Create the first dataframe
df1 = spark.createDataFrame([("A", 1), ("B", 2), ("C", 3)], ["letter", "number"])

# Create the second dataframe
df2 = spark.createDataFrame([("A", 4), ("B", 5), ("D", 6)], ["letter", "value"])

# Perform the inner join
inner_join = df1.join(df2, df1['letter'] == df2['letter'], "inner")

# Show the result of the join
inner_join.show()

# Output:
# +-----+------+-----+
# |letter|number|value|
# +-----+------+-----+
# |    A|     1|    4|
# |    B|     2|    5|
# +-----+------+-----+

В данном примере создаются два фрейма данных,  df1 и df2, с колонками letter и number, и letter и value, соответственно. Внутреннее соединение выполняется между df1 и df2 с использованием столбца letter в качестве ключа соединения. Результатом внутреннего соединения является новый фрейм данных, содержащий только те строки из df1 и df2 где значения в letter столбце совпадают. Результирующий фрейм данных содержит две строки для букв “A” и “B”, которые являются единственными буквами, присутствующими в обоих фреймах данных.

LEFT OUTER JOIN

Возвращает все строки из левого фрейма данных и совпадающие с ним строки из правого фрейма данных. Если в правом фрейме нет совпадающих значений, то возвращается null.

Синтаксис

df1.join(df2, df1['key'] == df2['key'], 'left').show()
(OR)
df1.join(df2, df1['key'] == df2['key'], 'leftouter').show()

В приведенном примере  df1 и df2 – это два объединяемых фрейма данных, а key – это столбец, который используется в качестве ключа объединения. Последний параметр,  'left', задает тип внешнего соединения.

Пример

Возьмем тот же набор данных, как и в предыдущем примере для внутреннего соединения:

# Perform the left outer join
left_outer_join = df1.join(df2, df1['letter'] == df2['letter'], "left_outer")

# Show the result of the join
left_outer_join.show()

# Output:
# +-----+------+-----+
# |letter|number|value|
# +-----+------+-----+
# |    A|     1|    4|
# |    B|     2|    5|
# |    C|     3| null|
# +-----+------+-----+

В данном примере создаются два фрейма данных,  df1 и df2, с колонками letter и number, и letter и value, соответственно. Между df1 и df2 выполняется левое внешнее соединение с использованием столбца letter в качестве ключа объединения. Результатом левого внешнего соединения является новый фрейм данных, содержащий все строки из левого фрейма (df1) и совпадающие строки из правого фрейма (df2), в данном случае – это столбец .

RIGHT OUTER JOIN

Возвращает все строки из правого фрейма данных и совпадающие строки из левого фрейма данных. Если в левом фрейме нет совпадающих значений, то возвращается null.

Синтаксис

df1.join(df2, df1['key'] == df2['key'], 'right').show()
(OR)
df1.join(df2, df1['key'] == df2['key'], 'rightouter').show()

В приведенном примере  df1 и df2 – это два объединяемых фрейма данных, а key – это столбец, который используется в качестве ключа объединения. Последний параметр,  'right', задает тип внешнего соединения, которое должно быть выполнено

Пример

Возьмем тот же набор данных, как и в первом примере для внутреннего соединения:

# Perform the right outer join
right_outer_join = df1.join(df2, df1['letter'] == df2['letter'], "right_outer")

# Show the result of the join
right_outer_join.show()

# Output:
# +-----+------+-----+
# |letter|number|value|
# +-----+------+-----+
# |    A|     1|    4|
# |    B|     2|    5|
# |    D|  null|    6|
# +-----+------+-----+

В данном случае создаются два фрейма данных,  df1 и df2, с колонками letter и number, и letter и value, соответственно. Между df1 и df2 выполняется правое внешнее соединение с использованием столбца letter в качестве ключа объединения. Результатом правого внешнего соединения является новый фрейм данных, содержащий все строки из правого фрейма (df2) и совпадающие строки из левого фрейма (df1). Если для строки из левого фрейма нет совпадений, то соответствующее значение в правом фрейме сохраняется, а столбцам из левого фрейма присваивается null значение.

OUTER / FULL JOIN

Возвращает все строки из обоих фреймов данных, включая совпадающие и не совпадающие строки. Если совпадающих значений нет, то результат будет содержать значение null вместо отсутствующих данных.

Синтаксис

df1.join(df2, df1['key'] == df2['key'], 'outer').show()
(OR)
df1.join(df2, df1['key'] == df2['key'], 'full').show()
(OR)
df1.join(df2, df1['key'] == df2['key'], 'fullouter').show()

В приведенном примере  df1 и df2 – это два объединяемых фрейма данных, а key – это столбец, который используется в качестве ключа объединения. Последний параметр,  'outer', задает тип внешнего соединения.

Пример

Используем тот же набор данных, как и в первом примере для внутреннего соединения:

# Perform the full outer join
full_outer_join = df1.join(df2, df1['letter'] == df2['letter'], "full_outer")

# Show the result of the join
full_outer_join.show()

# Output:
# +-----+------+-----+
# |letter|number|value|
# +-----+------+-----+
# |    A|     1|    4|
# |    B|     2|    5|
# |    C|     3| null|
# |    D|  null|    6|
# +-----+------+-----+

В данном примере создаются два фрейма данных,  df1 и df2, с колонками letter и number, и letter и value, соответственно. Между df1 и df2 выполняется полное внешнее объединение с использованием столбца letter в качестве ключа объединения. Результатом полного внешнего соединения является новый фрейм данных, содержащий все строки из обоих фреймов. Если строка в одном из них не совпадает, то соответствующее значение в другом фрейме сохраняется, а столбцам без совпадения присваивается null значение.

CROSS JOIN

Возвращает все возможные комбинации строк из обоих фреймов данных. Другими словами, берется каждая строка из одного фрейма данных и сопоставляется с каждой строкой в другом фрейме данных. В результате получается новый фрейм со всеми возможными комбинациями строк из двух входных фреймов данных.

Перекрестное соединение используется, когда мы хотим выполнить полное внешнее соединение, но более эффективным с точки зрения вычислений способом. Перекрестные соединения не рекомендуется использовать для больших наборов данных, поскольку они могут создавать очень большое количество записей, что приведет к проблемам с памятью и низкой производительности.

Синтаксис:

df1.crossJoin(df2).show()

В приведенном выше примере  df1 и df2 – это два фрейма данных, которые объединяются с помощью функции 'crossJoin'.

Пример

from pyspark.sql import SparkSession

# Create a Spark session
spark = SparkSession.builder.appName("CrossJoinExample").getOrCreate()

# Create the first dataframe
df1 = spark.createDataFrame([("A", 1), ("B", 2), ("C", 3)], ["letter", "number"])

# Create the second dataframe
df2 = spark.createDataFrame([("X", 4), ("Y", 5), ("Z", 6)], ["symbol", "value"])

# Perform the cross join
cross_join = df1.crossJoin(df2)

# Show the result of the join
cross_join.show()

# Output:
# +-----+------+------+-----+
# |letter|number|symbol|value|
# +-----+------+------+-----+
# |    A|     1|    X |   4 |
# |    A|     1|    Y |   5 |
# |    A|     1|    Z |   6 |
# |    B|     2|    X |   4 |
# |    B|     2|    Y |   5 |
# |    B|     2|    Z |   6 |
# |    C|     3|    X |   4 |
# |    C|     3|    Y |   5 |
# |    C|     3|    Z |   6 |
# +-----+------+------+-----+

В данном примере создаются два фрейма данных,  df1 и df2, с колонками letter и number, и symbol и value, соответственно. Между df1 и df2 выполняется перекрестное соединение. Результатом перекрестного соединения является новый фрейм данных, содержащий все возможные комбинации строк из обоих фреймов. В результате такого типа объединения получается большое количество дублирующихся строк, поэтому использовать его следует с осторожностью.

LEFT ANTI JOIN

Левое антисоединение в PySpark SQL – это тип операции левого соединения, который возвращает только те строки из левого фрейма данных, которые не имеют соответствующих значений в правом фрейме. Оно используется для поиска строк в одном фрейме данных, которые не имеют соответствующих значений в другом.

Результатом левого антисоединения является фрейм данных, содержащий только те строки из левого фрейма, которые не имеют совпадающих значений в правом. Если строка из левого фрейма имеет совпадающие значения в правом фрейме, то она не будет включена в результат.

Синтаксис:

df1.join(df2, df1['key'] == df2['key'], 'left_anti').show()

В приведенном примере  df1 и df2 – это два объединяемых фрейма данных, а key – это столбец, который используется в качестве ключа объединения. Последний параметр  'left_anti' указывает на то, что это левое антисоединение.

Пример

from pyspark.sql import SparkSession

# Create a Spark session
spark = SparkSession.builder.appName("LeftAntiJoinExample").getOrCreate()

# Create the first dataframe
df1 = spark.createDataFrame([("A", 1), ("B", 2), ("C", 3)], ["letter", "number"])

# Create the second dataframe
df2 = spark.createDataFrame([("A", 4), ("B", 5)], ["letter", "value"])

# Perform the left anti join
left_anti_join = df1.join(df2, df1['letter'] == df2['letter'], "left_anti")

# Show the result of the join
left_anti_join.show()

# Output:
# +-----+------+
# |letter|number|
# +-----+------+
# |    C|     3|
# +-----+------+

В данном примере создаются два фрейма данных,  df1 и df2, с колонками letter и number, и letter и value, соответственно. Между df1 и df2 столбцом letter в качестве ключа соединения выполняется левое антисоединение. Результатом левого антисоединения является новый фрейм данных, содержащий только те строки из первого фрейма (df1), которые не совпадают ни с одной строкой во втором фрейме (df2). Результат такого типа соединения включает только столбцы из первого фрейма, поскольку цель левого антисоединения – найти уникальные строки.

LEFT SEMI JOIN

Левое полусоединение в PySpark SQL – это тип операции присоединения, который возвращает только те столбцы из левого фрейма данных, которые имеют совпадающие значения в правом фрейме данных. Оно используется для поиска значений в одном фрейме, которые имеют соответствия в другом.

Результатом левого полусоединения является новый фрейм данных, содержащий только те столбцы из левого фрейма, которые имеют совпадающие значения в правом фрейме. Столбцы из правого фрейма данных в результат не включаются.

Синтаксис

df1.join(df2, df1['key'] == df2['key'], 'leftsemi').show()

В приведенном примере  df1 и df2 – это два объединяемых фрейма данных, а key – это столбец, который используется в качестве ключа объединения. Последний параметр  'leftsemi' указывает на то, что это левое полусоединение.

Пример

from pyspark.sql import SparkSession

# Create a Spark session
spark = SparkSession.builder.appName("LeftSemiJoinExample").getOrCreate()

# Create the first dataframe
df1 = spark.createDataFrame([("A", 1), ("B", 2), ("C", 3)], ["letter", "number"])

# Create the second dataframe
df2 = spark.createDataFrame([("A", 4), ("B", 5)], ["letter", "value"])

# Perform the left semi join
left_semi_join = df1.join(df2, df1['letter'] == df2['letter'], "leftsemi")

# Show the result of the join
left_semi_join.show()

# Output:
# +-----+------+
# |letter|number|
# +-----+------+
# |    A|     1|
# |    B|     2|
# +-----+------+

В данном примере создаются два фрейма данных,  df1 и df2, с колонками letter и number, и letter и value, соответственно. Между df1 и df2 столбцом letter в качестве ключа соединения выполняется левое полусоединение. Результатом левого полусоединения является новый фрейм данных, содержащий только те столбцы первого фрейма (df1), которые совпадают со строками второго фрейма (df2). Результат этого типа объединения включает только столбцы из первого фрейма, поскольку целью левого полусоединения является поиск строк в первом фрейме, которые совпадают со строками во втором фрейме.

SELF JOIN

Соединение внутри одной таблицы / самосоединение – это операция, при которой фрейм данных объединяется с самим собой. Она используется для сравнения значений в одном фрейме данных и возврата строк, соответствующих заданным критериям.

Например, самосоединение может быть использовано для поиска всех пар строк в фрейме данных, в которых значения в двух столбцах равны. В результате будет получен новый фрейм данных, содержащий только те строки, которые удовлетворяют заданным критериям.

Синтаксис

df.alias("df1").join(df.alias("df2"), df1['key'] == df2['key']).show()

В приведенном примере  df – это фрейм данных, который объединяется сам с собой, а key – это столбец, который используется в качестве ключа объединения. Для выполнения самосоединения фрейм данных должен иметь алиасы (alias) с двумя разными именами, в данном случае df1 и df2.

Пример

from pyspark.sql import SparkSession

# Create a Spark session
spark = SparkSession.builder.appName("SelfJoinExample").getOrCreate()

# Create a dataframe
df = spark.createDataFrame([("A", 1), ("B", 2), ("C", 3)], ["letter", "number"])

# Perform the self join
self_join = df.alias("df1").join(df.alias("df2"), df["letter"] == df["letter"])

# Show the result of the join
self_join.show()

# Output:
# +-----+------+-----+------+
# |letter|number|letter|number|
# +-----+------+-----+------+
# |    A|     1|    A|     1|
# |    B|     2|    B|     2|
# |    C|     3|    C|     3|
# +-----+------+-----+------+

В данном примере создается один фрейм данных df с колонками letter и number. В качестве ключа соединения используется столбец letter. Результатом самосоединения является новый фрейм данных, содержащий все комбинации строк между двумя экземплярами исходного фрейма данных. Для того чтобы различать два экземпляра исходного фрейма данных при соединении, им присваиваются уникальные алиасы.

Заключение

В этой статье мы подробно разобрали различные типы соединений таблиц в PySpark SQL на простых примерах с Python. Если у вас остались какие-либо вопросы, пишите их в комментариях.

Перевод статьи «Exploring the Different Join Types in Spark SQL: A Step-by-Step Guide».

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *