2015-10-19 11 views
13

में एकाधिक कॉलम विस्फोट (ट्रांसपोज़ करें?) मैं स्पार्क एसक्यूएल का उपयोग कर रहा हूं (मुझे लगता है कि यह स्पार्क में है जो SQL वाक्यविन्यास को प्रभावित करता है - मैं अभी तक सुनिश्चित करने के लिए पर्याप्त परिचित नहीं हूं) और मेरे पास तालिका जिसे मैं पुन: संरचना करने की कोशिश कर रहा हूं, लेकिन मैं एक ही समय में कई स्तंभों को स्थानांतरित करने की कोशिश कर रहा हूं।स्पार्क एसक्यूएल तालिका

मूल रूप से मैं डेटा है कि तरह लग रहा है:

userId someString  varA  varB 
    1  "example1" [0,2,5] [1,2,9] 
    2  "example2" [1,20,5] [9,null,6] 

और मैं एक साथ (लंबाई एकरूपता से किया जाएगा) दोनों Vara और varB विस्फोट करना चाहते हैं - तो यह है कि अंतिम आउटपुट इस तरह दिखता है:

userId someString  varA  varB 
    1  "example1"  0   1 
    1  "example1"  2   2 
    1  "example1"  5   9 
    2  "example2"  1   9 
    2  "example2"  20  null 
    2  "example2"  5   6 

लेकिन मैं उसके बाद ही मैं स्पष्ट रूप से प्राप्त एक भी विस्फोट (वर) बयान एक आदेश में काम करने के लिए प्राप्त करने के लिए लग सकता है, और अगर मैं उन्हें श्रृंखला की कोशिश करते हैं (यानी के बाद पहली आदेश विस्फोट एक अस्थायी तालिका बनाने के) एक डुप्लिकेट, अनावश्यक पंक्तियों की बड़ी संख्या।

बहुत धन्यवाद!

उत्तर

21

कस्टम यूडीएफ के बिना आप जो चाहते हैं वह संभव नहीं है। स्काला में आप कुछ इस तरह कर सकता है:

import org.apache.spark.sql.functions.{udf, explode} 

val zip = udf((xs: Seq[Long], ys: Seq[Long]) => xs.zip(ys)) 

df.withColumn("vars", explode(zip($"varA", $"varB"))).select(
    $"userId", $"someString", 
    $"vars._1".alias("varA"), $"vars._2".alias("varB")).show 

// +------+----------+----+----+ 
// |userId|someString|varA|varB| 
// +------+----------+----+----+ 
// |  1| example1| 0| 1| 
// |  1| example1| 2| 2| 
// |  1| example1| 5| 9| 
// |  2| example2| 1| 9| 
// |  2| example2| 20|null| 
// |  2| example2| 5| 6| 
// +------+----------+----+----+ 
कच्चे एसक्यूएल के साथ

:

val data = sc.parallelize(Seq(
    """{"userId": 1, "someString": "example1", 
     "varA": [0, 2, 5], "varB": [1, 2, 9]}""", 
    """{"userId": 2, "someString": "example2", 
     "varA": [1, 20, 5], "varB": [9, null, 6]}""" 
)) 

val df = sqlContext.read.json(data) 

df.printSchema 
// root 
// |-- someString: string (nullable = true) 
// |-- userId: long (nullable = true) 
// |-- varA: array (nullable = true) 
// | |-- element: long (containsNull = true) 
// |-- varB: array (nullable = true) 
// | |-- element: long (containsNull = true) 

अब हम zip यूडीएफ को परिभाषित कर सकते

sqlContext.udf.register("zip", (xs: Seq[Long], ys: Seq[Long]) => xs.zip(ys)) 
df.registerTempTable("df") 

sqlContext.sql(
    """SELECT userId, someString, explode(zip(varA, varB)) AS vars FROM df""") 
+0

यह 3 कॉलम के हैं पर लागू किया जा सकता है अनुक्रम टाइप करें? –

+0

@AmitKumar हाँ, क्यों नहीं? आपको हस्ताक्षर और शरीर को समायोजित करना होगा लेकिन यह मुश्किल नहीं है। – zero323

+0

मुझे आश्चर्य है कि क्या नए डेटासेट एपीआई में आप मानचित्र का उपयोग कर सकते हैं और यूडीएफ बनाये बिना सरणी को एक साथ ज़िप कर सकते हैं और क्या यह उत्प्रेरक निष्पादन इंजन द्वारा तेज़/स्केल/अनुकूलित किया जाएगा। कंसोल पर जब मैं कोशिश करूँगा। – Davos

संबंधित मुद्दे