Comment donner plus de conditions de colonne lors de la jonction de deux images. Par exemple, je veux exécuter ce qui suit:
val Lead_all = Leads.join(Utm_Master,
Leaddetails.columns("LeadSource","Utm_Source","Utm_Medium","Utm_Campaign") ==
Utm_Master.columns("LeadSource","Utm_Source","Utm_Medium","Utm_Campaign"),
"left")
Je veux rejoindre uniquement lorsque ces colonnes correspondent. Mais la syntaxe ci-dessus n'est pas valide car cols ne prend qu'une chaîne. Alors, comment puis-je obtenir ce que je veux.
Il existe un Spark jointure API de colonne/expression) pour un tel cas:
Leaddetails.join(
Utm_Master,
Leaddetails("LeadSource") <=> Utm_Master("LeadSource")
&& Leaddetails("Utm_Source") <=> Utm_Master("Utm_Source")
&& Leaddetails("Utm_Medium") <=> Utm_Master("Utm_Medium")
&& Leaddetails("Utm_Campaign") <=> Utm_Master("Utm_Campaign"),
"left"
)
L'opérateur <=>
Dans l'exemple signifie " test d'égalité sans danger pour les valeurs NULL ".
La principale différence avec simple test d’égalité (===
) Est que le premier est sûr à utiliser dans le cas où l’une des colonnes pourrait avoir une valeur nulle.
À partir de Spark version 1.5.0 (qui n'est pas encore publiée), vous pouvez rejoindre plusieurs colonnes DataFrame. Reportez-vous à SPARK-7990: Ajouter des méthodes pour faciliter l'équi-jointure sur plusieurs colonnes joindre des clés .
Python
Leads.join(
Utm_Master,
["LeadSource","Utm_Source","Utm_Medium","Utm_Campaign"],
"left_outer"
)
Scala
La question demandait une réponse Scala, mais je n'utilise pas Scala. Voici ma meilleure estimation ....
Leads.join(
Utm_Master,
Seq("LeadSource","Utm_Source","Utm_Medium","Utm_Campaign"),
"left_outer"
)
Une chose que vous pouvez faire est d'utiliser du SQL brut:
case class Bar(x1: Int, y1: Int, z1: Int, v1: String)
case class Foo(x2: Int, y2: Int, z2: Int, v2: String)
val bar = sqlContext.createDataFrame(sc.parallelize(
Bar(1, 1, 2, "bar") :: Bar(2, 3, 2, "bar") ::
Bar(3, 1, 2, "bar") :: Nil))
val foo = sqlContext.createDataFrame(sc.parallelize(
Foo(1, 1, 2, "foo") :: Foo(2, 1, 2, "foo") ::
Foo(3, 1, 2, "foo") :: Foo(4, 4, 4, "foo") :: Nil))
foo.registerTempTable("foo")
bar.registerTempTable("bar")
sqlContext.sql(
"SELECT * FROM foo LEFT JOIN bar ON x1 = x2 AND y1 = y2 AND z1 = z2")
Dans Pyspark, vous pouvez simplement spécifier chaque condition séparément:
val Lead_all = Leads.join(Utm_Master,
(Leaddetails.LeadSource == Utm_Master.LeadSource) &
(Leaddetails.Utm_Source == Utm_Master.Utm_Source) &
(Leaddetails.Utm_Medium == Utm_Master.Utm_Medium) &
(Leaddetails.Utm_Campaign == Utm_Master.Utm_Campaign))
Veillez simplement à utiliser correctement les opérateurs et les parenthèses.
Scala:
Leaddetails.join(
Utm_Master,
Leaddetails("LeadSource") <=> Utm_Master("LeadSource")
&& Leaddetails("Utm_Source") <=> Utm_Master("Utm_Source")
&& Leaddetails("Utm_Medium") <=> Utm_Master("Utm_Medium")
&& Leaddetails("Utm_Campaign") <=> Utm_Master("Utm_Campaign"),
"left"
)
pour le rendre insensible à la casse,
import org.Apache.spark.sql.functions.{lower, upper}
puis utilisez simplement lower(value)
dans la condition de la méthode join.
Par exemple: dataFrame.filter(lower(dataFrame.col("vendor")).equalTo("fortinet"))
Le ===
_ options me donnent des colonnes dupliquées. J'utilise donc Seq
à la place.
val Lead_all = Leads.join(Utm_Master,
Seq("Utm_Source","Utm_Medium","Utm_Campaign"),"left")
Bien entendu, cela ne fonctionne que lorsque les noms des colonnes qui se joignent sont identiques.
Essaye ça:
val rccJoin=dfRccDeuda.as("dfdeuda")
.join(dfRccCliente.as("dfcliente")
,col("dfdeuda.etarcid")===col("dfcliente.etarcid")
&& col("dfdeuda.etarcid")===col("dfcliente.etarcid"),"inner")
Spark SQL prend en charge la jointure sur plusieurs colonnes entre parenthèses, comme
... WHERE (list_of_columns1) = (list_of_columns2)
ce qui est un moyen plus court que de spécifier des expressions égales (=) pour chaque paire de colonnes combinées par un ensemble de "ET".
Par exemple:
SELECT a,b,c
FROM tab1 t1
WHERE
NOT EXISTS
( SELECT 1
FROM t1_except_t2_df e
WHERE (t1.a, t1.b, t1.c) = (e.a, e.b, e.c)
)
au lieu de
SELECT a,b,c
FROM tab1 t1
WHERE
NOT EXISTS
( SELECT 1
FROM t1_except_t2_df e
WHERE t1.a=e.a AND t1.b=e.b AND t1.c=e.c
)
ce qui est moins lisible, surtout quand la liste de colonnes est longue et que vous voulez traiter facilement les NULL.