sql - अपाचे स्पार्क जॉइन में शून्य मान शामिल हैं




scala apache-spark (2)

मैं अपाचे स्पार्क जॉइन में शून्य मान शामिल करना चाहूंगा। स्पार्क डिफ़ॉल्ट रूप से नल के साथ पंक्तियों को शामिल नहीं करता है।

यहाँ डिफ़ॉल्ट स्पार्क व्यवहार है।

val numbersDf = Seq(
  ("123"),
  ("456"),
  (null),
  ("")
).toDF("numbers")

val lettersDf = Seq(
  ("123", "abc"),
  ("456", "def"),
  (null, "zzz"),
  ("", "hhh")
).toDF("numbers", "letters")

val joinedDf = numbersDf.join(lettersDf, Seq("numbers"))

यहाँ joinedDf.show() का आउटपुट है:

+-------+-------+
|numbers|letters|
+-------+-------+
|    123|    abc|
|    456|    def|
|       |    hhh|
+-------+-------+

यह वह आउटपुट है जो मैं चाहूंगा:

+-------+-------+
|numbers|letters|
+-------+-------+
|    123|    abc|
|    456|    def|
|       |    hhh|
|   null|    zzz|
+-------+-------+

जॉय ऑपरेटर के परिणाम के लिए अशक्त पंक्तियों को शामिल करने के लिए निम्न विधि का प्रयास करें:

def nullSafeJoin(leftDF: DataFrame, rightDF: DataFrame, columns: Seq[String], joinType: String): DataFrame = {

    var columnsExpr: Column = leftDF(columns.head) <=> rightDF(columns.head)

    columns.drop(1).foreach(column => {
        columnsExpr = columnsExpr && (leftDF(column) <=> rightDF(column))
    })

    var joinedDF: DataFrame = leftDF.join(rightDF, columnsExpr, joinType)

    columns.foreach(column => {
        joinedDF = joinedDF.drop(leftDF(column))
    })

    joinedDF
}

स्पार्क एक विशेष NULL सुरक्षित समानता ऑपरेटर प्रदान करता है:

numbersDf
  .join(lettersDf, numbersDf("numbers") <=> lettersDf("numbers"))
  .drop(lettersDf("numbers"))
+-------+-------+
|numbers|letters|
+-------+-------+
|    123|    abc|
|    456|    def|
|   null|    zzz|
|       |    hhh|
+-------+-------+

सावधान रहें कि इसका उपयोग स्पार्क 1.5 या उससे पहले न करें। स्पार्क 1.6 से पहले इसे कार्टेशियन उत्पाद ( SPARK-11111 - फास्ट नल-सेफ जॉइन ) की आवश्यकता थी।

स्पार्क 2.3.0 में या बाद में आप Column.eqNullSafe में Column.eqNullSafe का उपयोग कर सकते हैं:

numbers_df = sc.parallelize([
    ("123", ), ("456", ), (None, ), ("", )
]).toDF(["numbers"])

letters_df = sc.parallelize([
    ("123", "abc"), ("456", "def"), (None, "zzz"), ("", "hhh")
]).toDF(["numbers", "letters"])

numbers_df.join(letters_df, numbers_df.numbers.eqNullSafe(letters_df.numbers))
+-------+-------+-------+
|numbers|numbers|letters|
+-------+-------+-------+
|    456|    456|    def|
|   null|   null|    zzz|
|       |       |    hhh|
|    123|    123|    abc|
+-------+-------+-------+

और स्पार्क में %<=>% :

numbers_df <- createDataFrame(data.frame(numbers = c("123", "456", NA, "")))
letters_df <- createDataFrame(data.frame(
  numbers = c("123", "456", NA, ""),
  letters = c("abc", "def", "zzz", "hhh")
))

head(join(numbers_df, letters_df, numbers_df$numbers %<=>% letters_df$numbers))
  numbers numbers letters
1     456     456     def
2    <NA>    <NA>     zzz
3                     hhh
4     123     123     abc

SQL ( स्पार्क 2.2.0+ ) के साथ आप IS NOT DISTINCT FROM उपयोग IS NOT DISTINCT FROM कर सकते हैं:

SELECT * FROM numbers JOIN letters 
ON numbers.numbers IS NOT DISTINCT FROM letters.numbers

इसका उपयोग DataFrame API के साथ भी किया जा सकता है:

numbersDf.alias("numbers")
  .join(lettersDf.alias("letters"))
  .where("numbers.numbers IS NOT DISTINCT FROM letters.numbers")




apache-spark-sql