Использование комбинаторики в Oracle SQL - PullRequest
0 голосов
/ 30 августа 2018

Можно использовать помощь или понимание, потому что я схожу с ума ..

  • Ситуация : у меня есть таблица идентификаторов игроков со значениями от 1,2,3 до 7.
  • Цель : Хотите создать список из 4 игроков из доступных игроков (в нашем случае их 7). Это классическая комбинаторная задача, нам нужно вычислить C (k, n). В нашем случае C (4,7) = 840/24 = 35. Итак, существует 35 возможных способов составить список. Я хочу создать таблицу списков с идентификаторами игроков. Вот текущий скрипт, который строит текущую учетную таблицу:

with comb_tbl as( select tmp_out.row_num, regexp_substr(tmp_out.comb_sets,'[^,]+',1,1) plr_id_1, regexp_substr(tmp_out.comb_sets,'[^,]+',1,2) plr_id_2, regexp_substr(tmp_out.comb_sets,'[^,]+',1,3) plr_id_3, regexp_substr(tmp_out.comb_sets,'[^,]+',1,4) plr_id_4 from( select rownum row_num, substr(tmp.combinations,2) comb_sets from( select sys_connect_by_path(plr.plr_id, ',') combinations from( select 1 plr_id from dual union select 2 plr_id from dual union select 3 plr_id from dual union select 4 plr_id from dual union select 5 plr_id from dual union select 6 plr_id from dual union select 7 plr_id from dual) plr connect by nocycle prior plr.plr_id != plr.plr_id) tmp where length(substr(tmp.combinations,2)) = 7) tmp_out) select tmp1.* from comb_tbl tmp1

  • Проблема : это создает 840 возможностей, но мне нужно удалить «идентичные», например, список (1,2,3,4) «идентичен» списку (2,1, 3,4). Любые идеи / комментарии / критики приветствуются. Может сам подход неправильный?

Ответы [ 3 ]

0 голосов
/ 30 августа 2018

Это может быть способ соединения:

with plr(plr_id) as 
    ( select level from dual connect by level <= 7)
select p1.plr_id, p2.plr_id, p3.plr_id, p4.plr_id
from plr p1
      inner join plr p2
        on(p1.plr_id < p2.plr_id)  
      inner join plr p3
        on(p2.plr_id < p3.plr_id)
      inner join plr p4
        on(p3.plr_id < p4.plr_id) 

Например, с n=5 вы бы получили:

    PLR_ID     PLR_ID     PLR_ID     PLR_ID
---------- ---------- ---------- ----------
         1          2          3          4
         1          2          3          5
         1          2          4          5
         1          3          4          5
         2          3          4          5
0 голосов
/ 30 августа 2018

Это не ответ; это просто продолжение моего предыдущего комментария:

После внесения этих дополнительных изменений ваш запрос может выглядеть примерно так:

SELECT regexp_substr(tmp_out.comb_sets,'[^,]+',1,1) plr_id_1,
       regexp_substr(tmp_out.comb_sets,'[^,]+',1,2) plr_id_2,
       regexp_substr(tmp_out.comb_sets,'[^,]+',1,3) plr_id_3,
       regexp_substr(tmp_out.comb_sets,'[^,]+',1,4) plr_id_4
FROM   (SELECT sys_connect_by_path(plr.plr_id, ',') comb_sets,
               LEVEL lvl
        FROM   (select 1 plr_id from dual union all
                select 2 plr_id from dual union all
                select 3 plr_id from dual union all
                select 4 plr_id from dual union all
                select 5 plr_id from dual union all
                select 6 plr_id from dual union all
                select 7 plr_id from dual) plr
        CONNECT BY PRIOR plr.plr_id < plr.plr_id
                   AND LEVEL <= 4) tmp_out
WHERE lvl = 4;

что, IMO, легче читать и понимать, чем ваш исходный запрос.

0 голосов
/ 30 августа 2018

Имеется соответствие 1-1 между возможными списками и упорядоченными подмножествами четырех элементов набора из семи элементов.

В вашем предложении CONNECT BY вы только проверяете, что идентификаторы игроков отличаются, а не в порядке возрастания. Измените != на < в CONNECT BY, и оно будет работать. (Кроме того, вам больше не понадобится NOCYCLE.)

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