Несколько подсчетов в одном запросе sql в искре scala - PullRequest
0 голосов
/ 04 февраля 2020

Я новый разработчик в Spark Scala, и у меня есть простая таблица, подобная этой:

City     Dept   employee_id   employee_salary
NY       FI     10            10000
NY       FI     null          20000
WDC      IT     30            100000    
LA       IT     40            500

Что я хочу сделать, это рассчитать:

  • количество сотрудников по городам и департаментам (простой счет (*))
  • количество сотрудников с ненулевым идентификатором
  • количество сотрудников с небольшим (<500) или средним ( <1000) или высокая зарплата (> 1000) => 3 дополнительных пункта!

Итак, в качестве вывода у меня должно быть что-то вроде этого:

City     Dept   total_emp   total_emp   total_emp_small  total_emp_medium  total_emp_high 
NY       FI     100         90         10                70               10 
WDC      IT     200         100    
LA       IT     10          10

Задача здесь в том, что я хочу оптимизировать эти показатели. Потому что, как вы видите, у нас здесь много дел. Без оптимизации грубая сила для меня - сделать один подсчет по запросу и сгенерировать новый результат DF после каждого подсчета, и в конце я делаю левое соединение на основе фиксированного столбца (city & dept), чтобы добавить эти новые столбцы. Но это будет слишком тяжело, так как моя таблица содержит много данных.

Я думаю, что метод "окно" может упростить это, но я не уверен.

Можете ли вы помочь мне в этом минимум с двумя случаями (id! = null и оклад <500). </p>

Заранее спасибо

1 Ответ

0 голосов
/ 04 февраля 2020
scala> df.show
+----+----+-----------+---------------+
|City|Dept|employee_id|employee_salary|
+----+----+-----------+---------------+
|  NY|  FI|         10|          10000|
|  NY|  FI|       null|          20000|
| WDC|  IT|         30|         100000|
|  LA|  IT|         40|            500|
|  LA|  IT|         40|            600|
|  LA|  IT|       null|            200|
+----+----+-----------+---------------+


scala> val df1 = df.withColumn("NonNullEmpID", when(col("employee_id").isNotNull, lit(1)).otherwise(lit(0)))
                   .withColumn("Salary_Cat", 
                               when(col("employee_salary") < 500, lit("SmallSalary")).
                               when(col("employee_salary") < 1000, lit("MediumSalary")).
                               when(col("employee_salary") >= 1000, lit("HighSalary")))

scala> val SalaryMap = df1.groupBy("Salary_Cat").agg(count(lit(1)).alias("count")).collect.flatMap(x => Map(x(0).toString -> x.toSeq.slice(1, x.length).mkString)).toMap

//the number of employees by city & department (a simple count(*))
//the number of employees with a non null id
//the number of employees with a small (< 500) or medium (< 1000) or high salary (> 1000) => 3 additional counts !

scala> df1.groupBy("City", "Dept")
          .agg(count(lit(1)).alias("#Emp_per_City_Dept"), sum(col("NonNullEmpID")).alias("NonNullEmpID"))
          .withColumn("total_emp_small", lit(SalaryMap("SmallSalary")))
          .withColumn("total_emp_medium", lit(SalaryMap("MediumSalary")))
          .withColumn("total_emp_high", lit(SalaryMap("HighSalary")))
          .show()
+----+----+------------------+------------+---------------+----------------+--------------+
|City|Dept|#Emp_per_City_Dept|NonNullEmpID|total_emp_small|total_emp_medium|total_emp_high|
+----+----+------------------+------------+---------------+----------------+--------------+
|  NY|  FI|                 2|           1|              1|               2|             3|
|  LA|  IT|                 3|           2|              1|               2|             3|
| WDC|  IT|                 1|           1|              1|               2|             3|
+----+----+------------------+------------+---------------+----------------+--------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...