[英]SQL to find combinations within a column
有一個包含兩列的表, PART_NUMBER
和PART_TYPE
。 一種類型可以有很多部分。 要求是使用sql過程找到部件號的唯一組合。 我們使用Oracle作為我們的數據庫。 樣本數據如下:
PART_NO PART_TYPE
Part1 10
Part2 10
Part3 10
Part4 20
Part5 30
Part6 30
Part7 40
我希望輸出如下。
1: Part1 Part4 Part5 Part7
2: Part1 Part4 Part6 Part7
3: Part2 Part4 Part5 Part7
4: Part2 Part4 Part6 Part7
5: Part3 Part4 Part5 Part7
6: Part3 Part4 Part6 Part7
ie)每種類型的每個部分形成單一組合。
請以算法或sql程序的形式對此進行一些說明。
使用分層查詢:
Oracle 11g R2架構設置 :
CREATE TABLE parts AS
SELECT 'Part1' AS PART_NO, 10 AS PART_TYPE FROM DUAL
UNION ALL SELECT 'Part2' AS PART_NO, 10 AS PART_TYPE FROM DUAL
UNION ALL SELECT 'Part3' AS PART_NO, 10 AS PART_TYPE FROM DUAL
UNION ALL SELECT 'Part4' AS PART_NO, 20 AS PART_TYPE FROM DUAL
UNION ALL SELECT 'Part5' AS PART_NO, 30 AS PART_TYPE FROM DUAL
UNION ALL SELECT 'Part6' AS PART_NO, 30 AS PART_TYPE FROM DUAL
UNION ALL SELECT 'Part7' AS PART_NO, 40 AS PART_TYPE FROM DUAL;
查詢1 :
WITH combinations AS (
SELECT SYS_CONNECT_BY_PATH( PART_NO, ' ' ) AS parts,
CONNECT_BY_ISLEAF AS leaf
FROM parts
START WITH PART_TYPE = 10
CONNECT BY PRIOR PART_TYPE + 10 = PART_TYPE
)
SELECT ROWNUM || ':' || parts AS output
FROM combinations
WHERE leaf = 1
結果 :
| OUTPUT |
|----------------------------|
| 1: Part1 Part4 Part5 Part7 |
| 2: Part1 Part4 Part6 Part7 |
| 3: Part2 Part4 Part5 Part7 |
| 4: Part2 Part4 Part6 Part7 |
| 5: Part3 Part4 Part5 Part7 |
| 6: Part3 Part4 Part6 Part7 |
編輯Rob van Wijk :由於在連接后評估了connect_by_isleaf,因此稍微簡單一點的查詢是:
SQL> select rownum || ':' || sys_connect_by_path(part_no, ' ') as parts
2 from parts
3 where connect_by_isleaf = 1
4 connect by prior part_type + 10 = part_type
5 start with part_type = 10
6 /
PARTS
---------------------------------------------------------------------------------------
1: Part1 Part4 Part5 Part7
2: Part1 Part4 Part6 Part7
3: Part2 Part4 Part5 Part7
4: Part2 Part4 Part6 Part7
5: Part3 Part4 Part5 Part7
6: Part3 Part4 Part6 Part7
6 rows selected.
編輯 - 非增量PART_TYPE
問題3 :
WITH part_types AS (
SELECT DISTINCT PART_TYPE
FROM parts
),
ordered_part_types AS (
SELECT PART_TYPE,
LEAD( PART_TYPE ) OVER ( ORDER BY PART_TYPE ) AS NEXT_PART_TYPE
FROM part_types
)
SELECT ROWNUM || ':' || SYS_CONNECT_BY_PATH( PART_NO, ' ' ) AS parts
FROM parts p
INNER JOIN
ordered_part_types t
ON ( p.PART_TYPE = t.PART_TYPE )
WHERE CONNECT_BY_ISLEAF = 1
START WITH p.PART_TYPE = ( SELECT MIN( PART_TYPE ) FROM parts )
CONNECT BY PRIOR NEXT_PART_TYPE = p.PART_TYPE
結果 :
| PARTS |
|----------------------------|
| 1: Part3 Part4 Part6 Part7 |
| 2: Part3 Part4 Part5 Part7 |
| 3: Part2 Part4 Part6 Part7 |
| 4: Part2 Part4 Part5 Part7 |
| 5: Part1 Part4 Part6 Part7 |
| 6: Part1 Part4 Part5 Part7 |
你不需要PL / SQL。 只是SQL。
with TAB as (
select 'Part1' as PART_NO, 10 as PART_TYPE from dual union all
select 'Part2', 10 from dual union all
select 'Part3', 10 from dual union all
select 'Part4', 20 from dual union all
select 'Part5', 30 from dual union all
select 'Part6', 30 from dual union all
select 'Part7', 40 from dual
),
CONSTANTS as (
select /*+ MATERIALIZE */
min( PART_TYPE ) as PART_TYPE,
count( distinct PART_TYPE ) as CNT
from TAB
)
select rownum || ':' || ANSWER as ANSWER
from ( select sys_connect_by_path( PART_NO, ' ' ) as ANSWER,
connect_by_isleaf as IS_LEAF,
level as L
from TAB
start with PART_TYPE = ( select PART_TYPE
from CONSTANTS )
connect by PART_TYPE > prior PART_TYPE )
where L = ( select CNT
from CONSTANTS )
and IS_LEAF = 1
這將為您提供所需的輸出,但需要注意:
1:您必須在FROM
子句中為每個part_type
添加一個表,並在where子句中添加“less than”行。
2:注意:如果基表很大, 笛卡爾連接可能會使它永遠運行(或多或少)。
with tab as (
select 'Part1' part_no, 10 part_type from dual union all
select 'Part2', 10 from dual union all
select 'Part3', 10 from dual union all
select 'Part4', 20 from dual union all
select 'Part5', 30 from dual union all
select 'Part6', 30 from dual union all
select 'Part7', 40 from dual
)
select
t1.part_no||','||t2.part_no||','||t3.part_no||','||t4.part_no output
from
tab t1, tab t2, tab t3, tab t4
where
t1.part_type < t2.part_type and
t2.part_type < t3.part_type and
t3.part_type < t4.part_type
order by 1;
您可以使用Oracle的listagg函數(請參閱https://docs.oracle.com/database/121/SQLRF/functions100.htm#SQLRF30030 ),如下所示:
select part_type, listagg(part_no, ' ') within group (order by part_no)
from d
group by part_type;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.