Dəyərli dostlar,

Bu yaxınlarda kifayət qədər maraqlı bir SQL məsələsini müxtəlif şəbəkələrdə elan etdim. Geri dönüşlərdən o qənaətə gəldim ki, həllini izah etməyə ehtiyac var.

Beləliklə,

Məsələnin şərtini qeyd edək:

a ve b ədədlərindən ibarət verilmiş uzunluqda bütün kombinasiyaları SQL ilə çıxarmaq lazımdır.

 

Məsələn,

I) uzunluq 2 olaraq verilərsə, nəticə aşağıdakı şəkildə olmalıdır:

aa

ab

ba

bb

 

II) uzunluq 3 olaraq verilərsə, nəticə aşağıdakı şəkildə olmalıdır:

aaa

aab

aba

abb

baa

bab

bba

bbb

 

Hər bir məsələnin həllində olduğu kimi, bu məsələnin də həllində ilkin olaraq, bir qanunauyğunluq tapmağa çalışaq. Beləki, nəticələrin nümunəsinə nəzər yetirsək, a hərfini 0 və b hərfini 1 kimi təsəvvür etsək, hər bir sətir həmin sətrin sıra nömrəsindən bir vahid az ədədin 2-lik say sistemində ifadə olunmuş formasıdır.  Ümumi sətrlərin sayı isə 2^n qaydası ilə təyin olunacaq.

Yəni

aa >> 00

ab >> 01

ba >> 10

bb >> 11

 

Bu yanaşma ilə məsələni 3 hissəyə parçalayaq:

1) Ardıcıl N (N=2^n) sətrin alınması;

2) Hər sətrdəki (10-luq say sistemində olan)  ədədin  (sıra nömrəsi -1) 2-lik say sisteminə çevrilməsi;

3) Alınmış nəticədə 0-in ‘a’, 1-in  ‘b’ simvoluna çevrilməsi.

 

N uzunluğunu ilkin olaraq 3-də bərabər hesab edək və ardıcıl olaraq yuxarıdakı mərhələləri SQL ilə yazaq:

1) Ardıcıl 8 (N=2^3) sətrin alınması:

Hər sətirdə həmin sətrin sıra nömrəsi -1 olan ədədi çıxarıraq.

select level-1 as base_10
from dual
connect by level<=power(2,3);

2) Hər sətrdə olan ədədin 2-lik saysisteminə çevrilməsi:

Bu mərhələ həlledici mərhələdir. Bir ədədi 10-luq say sistemindən 2-lik say sisteminə çevirmək üçün, heç bir standart SQL funksiyası istifadə etmədən, hətta məktəb proqramından bildiyimizin qaydanı tətbiq edəcəyəm.  Ümumi qayda 10-luq ədədi 2-yə bölməklə, sonda alınan qismət və geriyə doğru qalıqları yanaşı yazılmasıdır.

Həmin məntiqi SQL-ə çevirək:

with seq as (select level-1 as base_10 from dual connect by level<=power(2,3)),
len as (select level as pos from dual connect by level<=3),
tab as (select base_10, mod(trunc( base_10/( power( 2,(pos-1) ) )) , 2) base_2, pos from len, seq)
select base_10, reverse(listagg(base_2, ”) within group (order by pos)) as “Result”
from tab
group by base_10
order by 1;

3) Alınmış nəticədə 0-in ‘a’, 1-in  ‘b’ simvoluna çevrilməsi:

with seq as (select level-1 as base_10 from dual connect by level<=power(2,3)),
len as (select level as pos from dual connect by level<=3),
tab as (select base_10, mod(trunc( base_10/( power( 2,(pos-1) ) )) , 2) base_2, pos from len, seq)
select base_10, translate(reverse(listagg(base_2, ”) within group (order by pos)), ’01’ , ‘ab’ ) as “Result”
from tab
group by base_10
order by 1;

Beləliklə son SQL-i dinamikləşdirmək üçün, qəbul etdiyimiz N=3 ədədinin əvəzinə Substitution Variable  (&N) istifadə edə bilərik:

WITH seq AS (
SELECT level – 1 AS base_10
FROM dual
CONNECT BY level <= power(2, &n)
),
len AS (
SELECT level AS pos
FROM dual
CONNECT BY level <= &n
),
tab AS (
SELECT base_10,
mod(trunc(base_10 /(power(2,(pos – 1)))), 2) base_2,
pos
FROM len, seq
)
SELECT
base_10,
translate(reverse(
LISTAGG(base_2, ”) WITHIN GROUP(ORDER BY pos)
), ’01’, ‘ab’) AS “Result”
FROM tab
GROUP BY base_10
ORDER BY 1;

 

 

Bundan əlavə digər təklif olunan variantları aşağıda müəllifləri ilə təqdim edirəm:

Arifə Məmmədzadə (Tələbəm, Junior Database Developer) :

select t,lpad(
(SELECT LISTAGG(SIGN(BITAND(t, POWER(2, LEVEL – 1))), ”) WITHIN GROUP(ORDER BY LEVEL DESC) bin FROM dual
CONNECT BY POWER(2, LEVEL – 1) <= t),
&d, 0) as combination
from (SELECT LEVEL – 1 as t FROM DUAL
CONNECT BY LEVEL <=(select power(digit, len)
from (select 2 as digit, &d as len from dual)));

 

Mahir Eynullayev (Ekspert):

select replace(REPLACE((lpad((SELECT LISTAGG(SIGN(BITAND(mylevel, POWER(2,LEVEL-1))),”)
WITHIN GROUP(ORDER BY LEVEL DESC) bin
FROM dual
CONNECT BY POWER(2, LEVEL-1)<=mylevel),4, ‘0’)), ‘0’, ‘a’),’1′,’b’)
from (select level-1 as mylevel from dual connect by level<=power(2,4));

 

Cavad Paşayev ( https://t.me/oraclesql  telegram qrupumuzdan) :

select * from
(with combinations(c) as
(
select chr( ascii(‘0’) + level -1)
from dual connect by level <= 2
)
select replace (sys_connect_by_path(c, ‘ ‘), ‘ ‘, ”) as result
from combinations connect by level <= 8 — Uzunluq burda təyin olunur
order by level, result)
where length(result) = 8; — Uzunluq burda təyin olunur

 

 

Ruslan Cəlilov (Peşəkar) :

WITH TMP1 AS
(
SELECT LEVEL-1 R
FROM DUAL
CONNECT BY LEVEL <= POWER(2, :PARAM)
)
, TMP2 AS
(
SELECT LPAD(
(
SELECT LISTAGG(SIGN(BITAND(R, POWER(2,LEVEL-1))),”)
WITHIN GROUP(ORDER BY LEVEL DESC) bin
FROM dual
CONNECT BY POWER(2, LEVEL-1)<=R
), :PARAM, ‘0’) AS C
FROM TMP1
)
SELECT REPLACE(REPLACE(C, ‘0’, ‘a’), ‘1’, ‘b’) AS RES
FROM TMP2;

 

Leave a comment