Несколько групп по и несколько отображения счетчика на спарк sql? - PullRequest
0 голосов
/ 04 января 2019

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

Employee     Sub_department   Department 
A               105182          10
A               105182          10   (data can be redundant !)   
A               114256          11
A               127855          12
A               125182          12
B               136234          13
B               133468          13

Отдел определяется как подстрока (sub_department, 0, 2) для извлечения только первых 2 цифр sub_department.

То, что я хочу показать, это разделить 3 типа сотрудников:

  • Набор 1: Сотрудники, имеющие как минимум 3 разных отдела (независимо от их подотделов)
  • Набор 1: сотрудники, имеющие как минимум 5 разных подотделов И 2 разных отдела
  • Набор 3: Сотрудники, имеющие не менее 10 различных подотделов с одним и тем же отделом

Конкретно я понятия не имею, как это сделать даже в классическом SQL. Но, по крайней мере, я думаю, что конечный результат может быть примерно таким:

Employee     Sub_department   total_sub_dept  Department  total_dept 
A               105182          4                10           3     
A               114256          4                11           3
A               127855          4                12           3
A               125182          4                12           3

И "в конце концов" столбец с именем "Set", показывающий, к какому набору может принадлежать сотрудник, но это необязательно, и я боюсь, что это будет слишком тяжело для вычисления такого значения ...

Важно отобразить различные значения И счетчик для каждого из 2 столбцов (подразделение и отдел).

У меня очень большая таблица (со многими столбцами и множеством данных, которые могут быть избыточными), поэтому я решил сделать это, используя первый раздел в sub_department и сохранить его в первой таблице. Затем второй раздел в отделе (независимо от значения «sub_department») и сохраните его во второй таблице. И, наконец, сделайте внутреннее соединение двух таблиц на основе имени сотрудника.

Но я получил некоторые неправильные результаты, и я не знаю, есть ли лучший способ сделать это? или, по крайней мере, иметь оптимизацию, так как столбец отдела зависит от sub_department (чтобы сделать одну группу вместо 2).

Итак, как мне это исправить, пожалуйста? Я пытался, но кажется невозможным объединить счетчик (столбец) с одним и тем же столбцом для каждого из 2 столбцов ...

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

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Вы можете использовать оконные функции collect_set () и получить результаты. Проверьте это

scala> val df = Seq(("A","105182","10"), ("A","105182","10" ), ("A","114256","11"), ("A","127855","12"), ("A","125182","12"), ("B","136234","13"), ("B","133468","13")).toDF("emp","subdept","dept")
df: org.apache.spark.sql.DataFrame = [emp: string, subdept: string ... 1 more field]

scala> df.printSchema
root
 |-- emp: string (nullable = true)
 |-- subdept: string (nullable = true)
 |-- dept: string (nullable = true)


scala> df.show
+---+-------+----+
|emp|subdept|dept|
+---+-------+----+
|  A| 105182|  10|
|  A| 105182|  10|
|  A| 114256|  11|
|  A| 127855|  12|
|  A| 125182|  12|
|  B| 136234|  13|
|  B| 133468|  13|
+---+-------+----+


scala> val df2 = df.withColumn("dept2",substring('subdept,3,7))
df2: org.apache.spark.sql.DataFrame = [emp: string, subdept: string ... 2 more fields]

scala> df2.createOrReplaceTempView("salaman")

scala> spark.sql(""" select *, size(collect_set(subdept) over(partition by emp)) sub_dep_count, size(collect_set(dept) over(partition by emp)) dep_count from salaman """).show(false)
+---+-------+----+-----+-------------+---------+
|emp|subdept|dept|dept2|sub_dep_count|dep_count|
+---+-------+----+-----+-------------+---------+
|B  |136234 |13  |6234 |2            |1        |
|B  |133468 |13  |3468 |2            |1        |
|A  |105182 |10  |5182 |4            |3        |
|A  |105182 |10  |5182 |4            |3        |
|A  |125182 |12  |5182 |4            |3        |
|A  |114256 |11  |4256 |4            |3        |
|A  |127855 |12  |7855 |4            |3        |
+---+-------+----+-----+-------------+---------+


scala>
0 голосов
/ 04 января 2019

Салман, люди на SO проголосуют, если вы не опубликуете код, который пробовали до сих пор. Я помогу вам с требованием в наборе 1, просто чтобы поощрить вас. Пожалуйста, постарайтесь понять приведенный ниже запрос. После этого очень просто выполнить набор 2 и установить 3.

SELECT 
 employee
 total_dept
FROM
(
 SELECT
  employee
  COUNT(Department) AS total_dept
 FROM
 (
  select 
    employee,
    Sub_department,
    SUBSTRING(Sub_department,0,2) AS Department,
    ROW_NUMBER() OVER (partition by employee,SUBSTRING(Sub_department,0,2)) AS redundancy 
  FROM
  table
 )
 WHERE redundancy = 1
 GROUP BY employee
) WHERE total_dept >= 3

EDIT1:

SELECT 
 full_data.employee,
 full_data.sub_department,
 total_sub_dept_count.total_sub_dept
 full_data.SUBSTRING(Sub_department,0,2) AS Department
 total_dept_count.total_dept
FROM
(
 SELECT
  employee
  COUNT(Department) AS total_dept
 FROM
 (
  select 
    employee,
    Sub_department,
    SUBSTRING(Sub_department,0,2) AS Department,
    ROW_NUMBER() OVER (partition by employee,SUBSTRING(Sub_department,0,2)) AS redundancy 
  FROM
  employee_table
 )
 WHERE redundancy = 1
 GROUP BY employee
) total_dept_count
JOIN
(
 SELECT
  employee
  COUNT(department) AS total_sub_dept
 FROM
 (
  select 
    employee,
    department,
    ROW_NUMBER() OVER (partition by employee,department) AS redundancy 
  FROM
  employee_table
 )
 WHERE redundancy = 1
 GROUP BY employee
) total_sub_dept_count
ON(total_dept_count.employee = total_sub_dept_count.employee)
JOIN
 employee_table full_data
ON(total_sub_dept_count.employee = full_data.employee)
...