SQL - Как можно суммировать элементы массива? - PullRequest
0 голосов
/ 27 марта 2020

Я использую SQL с pyspark и hive, и я новичок во всем этом. У меня есть таблица кустов со столбцом типа строка, например:

id | values
1  | '2;4;4'
2  |  '5;1'
3  |  '8;0;4'

Я хочу создать запрос для получения этого:

id | values | sum
1  | '2.2;4;4'  | 10.2
2  |  '5;1.2' |  6.2
3  |  '8;0;4' | 12

Используя split (values, ' ; ') Я могу получить массивы типа [' 2.2 ',' 4 ',' 4 '], но мне все еще нужно преобразовать их в десятичные числа и суммировать их. Есть ли не слишком сложный способ сделать это?

Заранее большое спасибо! И счастливого вам кодирования:)

Ответы [ 3 ]

2 голосов
/ 28 марта 2020

С Spark-2.4+

Нам не нужно использовать explode для массивов, но напрямую работать с массивами, используя функции более высокого порядка .

Example:

from pyspark.sql.functions import *

df=spark.createDataFrame([("1","2;4;4"),("2","5;1"),("3","8;0;4")],["id","values"])

#split and creating array<int> column
df1=df.withColumn("arr",split(col("values"),";").cast("array<int>"))

df1.createOrReplaceTempView("tmp")

spark.sql("select *,aggregate(arr,0,(x,y) -> x + y) as sum from tmp").drop("arr").show()
#+---+------+---+
#| id|values|sum|
#+---+------+---+
#|  1| 2;4;4| 10|
#|  2|   5;1|  6|
#|  3| 8;0;4| 12|
#+---+------+---+

#in dataframe API

df1.selectExpr("*","aggregate(arr,0,(x,y) -> x + y) as sum").drop("arr").show()
#+---+------+---+
#| id|values|sum|
#+---+------+---+
#|  1| 2;4;4| 10|
#|  2|   5;1|  6|
#|  3| 8;0;4| 12|
#+---+------+---+
1 голос
/ 28 марта 2020

Решение PySpark

from pyspark.sql.functions import udf,col,split
from pyspark.sql.types import FloatType 
#UDF to sum the split values returning none when non numeric values exist in the string
#Change the implementation of the function as needed
def values_sum(split_list):
    total = 0
    for num in split_list:
        try:
            total += float(num)
        except ValueError:
            return None
    return total

values_summed = udf(values_sum,FloatType())
res = df.withColumn('summed',values_summed(split(col('values'),';')))
res.show()

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

Решение Hive

Используйте explode с split и group by для суммирования значений.

select id,sum(cast(split_value as float)) as summed
from tbl
lateral view explode(split(values,';')) t as split_value
group by id
0 голосов
/ 28 марта 2020

написать хранимую процедуру , которая выполняет работу:

CREATE FUNCTION SPLIT_AND_SUM ( s VARCHAR(1024) ) RETURNS INT
BEGIN
   ...
END
...