Подсчет столбца через запятую значения оракула - PullRequest
0 голосов
/ 14 октября 2019

Можно ли считать и группировать значения через запятую в таблице базы данных oracle? Это пример табличных данных:

id | user | title | 
1  | foo  | a,b,c |
2  | bar  | a,d   |
3  | tee  | b     |

Ожидаемый результат будет:

title | count
a     | 2
b     | 2
c     | 1
d     | 1

Я хотел использовать concat следующим образом:

SELECT a.title FROM Account a WHERE concat(',', a.title, ',') LIKE 'a' OR concat(',', a.title, ',') LIKE 'b' ... GROUP BY a.title?

Но яполучаю invalid number of arguments на конкат. Значения заголовка предопределены, поэтому я не возражаю, если мне придется перечислить все из них в запросе. Любая помощь с благодарностью.

Ответы [ 2 ]

1 голос
/ 14 октября 2019

При этом используются простые строковые функции и рекурсивный факторинг подзапроса, и он может быть быстрее, чем использование регулярных выражений и коррелированных объединений:

Установка Oracle :

CREATE TABLE account ( id, "user", title ) AS
  SELECT 1, 'foo', 'a,b,c' FROM DUAL UNION ALL
  SELECT 2, 'bar', 'a,d'   FROM DUAL UNION ALL
  SELECT 3, 'tee', 'b'     FROM DUAL;

Запрос :

WITH positions ( title, start_pos, end_pos ) AS (
  SELECT title,
         1,
         INSTR( title, ',', 1 )
  FROM   account
UNION ALL
  SELECT title,
         end_pos + 1,
         INSTR( title, ',', end_pos + 1 )
  FROM   positions
  WHERE  end_pos > 0
),
items ( item ) AS (
  SELECT CASE end_pos
         WHEN 0
         THEN SUBSTR( title, start_pos )
         ELSE SUBSTR( title, start_pos, end_pos - start_pos )
         END
  FROM   positions
)
SELECT item,
       COUNT(*)
FROM   items
GROUP BY item
ORDER BY item;

Выход :

ITEM | COUNT(*)
:--- | -------:
a    |        2
b    |        2
c    |        1
d    |        1

дБ <> скрипка здесь

1 голос
/ 14 октября 2019

Разделите заголовки на строки и сосчитайте их.

SQL> with test (id, title) as
  2    (select 1, 'a,b,c' from dual union all
  3     select 2, 'a,d'   from dual union all
  4     select 3, 'b'     from dual
  5    ),
  6  temp as
  7    (select regexp_substr(title, '[^,]', 1, column_value) val
  8     from test cross join table(cast(multiset(select level from dual
  9                                              connect by level <= regexp_count(title, ',') + 1
 10                                             ) as sys.odcinumberlist))
 11    )
 12  select val as title,
 13         count(*)
 14  From temp
 15  group by val
 16  order by val;

TITLE                  COUNT(*)
-------------------- ----------
a                             2
b                             2
c                             1
d                             1

SQL>

Если заголовки не так просты, измените REGEXP_SUBSTR (добавьте + знак) в строке № 7, например

SQL> with test (id, title) as
  2    (select 1, 'Robin Hood,Avatar,Star Wars Episode III' from dual union all
  3     select 2, 'Mickey Mouse,Avatar'   from dual union all
  4     select 3, 'The Godfather'     from dual
  5    ),
  6  temp as
  7    (select regexp_substr(title, '[^,]+', 1, column_value) val
  8     from test cross join table(cast(multiset(select level from dual
  9                                              connect by level <= regexp_count(title, ',') + 1
 10                                             ) as sys.odcinumberlist))
 11    )
 12  select val as title,
 13         count(*)
 14  From temp
 15  group by val
 16  order by val;

TITLE                            COUNT(*)
------------------------------ ----------
Avatar                                  2
Mickey Mouse                            1
Robin Hood                              1
Star Wars Episode III                   1
The Godfather                           1

SQL>
...