Как сравнить идентификаторы с разделенной запятыми строкой в ​​Oracle SQL? - PullRequest
0 голосов
/ 08 ноября 2019

У меня есть две таблицы, например, «Сотрудники» и «Проекты». Мне нужен список всех проектов с указанием всех задействованных сотрудников. Теперь проблема заключается в том, что значения employee_ids сохраняются с запятыми, как в примере ниже:

employe  | ID          project   | employe_id
--------------         -----------------------
Person A | 1           Project X | ,2,
Person B | 2           Project Y | 
Person C | 3           Project Z | ,1,3,

select 
p.project, e.employe
from 
projects p
left join employees e on e.id = p.employe_id ???

Как мне написать объединение, чтобы получить желаемый результат:

project   | employe
--------------------
Project X | Person B,
Project Y |
Project Z | Person A, Person C

Ответы [ 4 ]

1 голос
/ 08 ноября 2019

Вы можете попробовать group by и listagg следующим образом:

select 
p.project, 
listagg(e.employe,',') within group (order by e.id) as employee
from 
projects p
left join employees e on p.employe_id like  '%,' || e.id || ',%'
Group by p.project

Ура !!

0 голосов
/ 08 ноября 2019

Еще один вариант;код, который вам нужен (поскольку у вас уже есть эти таблицы), начинается со строки № 12:

SQL> -- Your sample data
SQL> with employees (employee, id) as
  2    (select 'Person A', 1 from dual union all
  3     select 'Person B', 2 from dual union all
  4     select 'Person C', 3 from dual
  5    ),
  6  projects (project, employee_id) as
  7    (select 'Project X', ',2,'   from dual union all
  8     select 'Project Y', null    from dual union all
  9     select 'Project Z', ',1,3,' from dual
 10    ),
 11  -- Employees per project
 12  emperpro as
 13    (select project, regexp_substr(employee_id, '[^,]+', 1, column_value) id
 14     from projects cross join table(cast(multiset(select level from dual
 15                                                  connect by level <= regexp_count(employee_id, ',') + 1
 16                                                 ) as sys.odcinumberlist))
 17    )
 18  -- Final result
 19  select p.project, listagg(e.employee, ', ') within group (order by null) employee
 20  from emperpro p left join employees e on e.id = p.id
 21  group by p.project
 22  /

PROJECT   EMPLOYEE
--------- ----------------------------------------
Project X Person B
Project Y
Project Z Person A, Person C

SQL>
0 голосов
/ 08 ноября 2019

Вы можете извлечь числовые идентификаторы из столбца employee_id таблицы projects, используя вместе функции regexp_substr() и rtrim() (, обрезая последнюю лишнюю запятую ), а затем объединить с помощьюlistagg() функция:

with p2 as
(
select distinct p.*, regexp_substr(rtrim(p.employee_id,','),'[^,]',1,level) as p_eid, 
       level as rn
  from projects p
connect by level <= regexp_count(rtrim(p.employee_id,','),',') 
)
select p2.project, listagg(e.employee,', ') within group (order by p2.rn) as employee
  from p2
  left join employees e on e.id = p2.p_eid
 group by p2.project 

Демо

0 голосов
/ 08 ноября 2019

Вот забавный способ сделать это:

WITH cteId_counts_by_project AS (SELECT PROJECT,
                                        NVL(REGEXP_COUNT(EMPLOYE_ID, '[^,]'), 0) AS ID_COUNT
                                   FROM PROJECTS),
     cteMax_id_count AS (SELECT MAX(ID_COUNT) AS MAX_ID_COUNT
                           FROM cteId_counts_by_project),
     cteProject_employee_ids AS (SELECT PROJECT,
                                        EMPLOYE_ID,
                                        REGEXP_SUBSTR(EMPLOYE_ID, '[^,]',1, LEVEL) AS ID
                                   FROM PROJECTS
                                   CROSS JOIN cteMax_id_count m
                                   CONNECT BY LEVEL <= m.MAX_ID_COUNT),
     cteProject_emps AS (SELECT DISTINCT PROJECT, ID
                           FROM cteProject_employee_ids
                           WHERE ID IS NOT NULL),
     cteProject_empnames AS (SELECT pe.PROJECT, pe.ID, e.EMPLOYE
                               FROM cteProject_emps pe
                               LEFT OUTER JOIN EMPLOYEES e
                                 ON e.ID = pe.ID
                               ORDER BY pe.PROJECT, e.EMPLOYE)
SELECT p.PROJECT,
       LISTAGG(pe.EMPLOYE, ',') WITHIN GROUP (ORDER BY pe.EMPLOYE) AS EMPLOYEE_LIST
  FROM PROJECTS p
  LEFT OUTER JOIN cteProject_empnames pe
    ON pe.PROJECT = p.PROJECT
  GROUP BY p.PROJECT
  ORDER BY p.PROJECT

Вы, конечно, можете сжать некоторые из CTE вместе, чтобы сэкономить место, но я держал их отдельно, чтобы вы могли видеть, как каждый маленький бит добавляет крешение.

dbfiddle здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...