簡體   English   中英

SQL用於查找列中的組合

[英]SQL to find combinations within a column

有一個包含兩列的表, PART_NUMBERPART_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程序的形式對此進行一些說明。

使用分層查詢:

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

SQL小提琴

問題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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM