假設我們要辦商品促銷,想得商品的組合.
create table it200117a (
id smallint generated always as identity
, prdct_nme text not null
);
insert into it200117a (prdct_nme) values
('三角鉛筆'),('藍桿鉛筆'),('黃桿鉛筆'),('學習鉛筆'),('代針筆');
corss join 會得到:
select a.prdct_nme
, b.prdct_nme
from it200117a a
cross join it200117a b;
+-----------+-----------+
| prdct_nme | prdct_nme |
+-----------+-----------+
| 三角鉛筆 | 三角鉛筆 |
| 三角鉛筆 | 藍桿鉛筆 |
| 三角鉛筆 | 黃桿鉛筆 |
...
| 代針筆 | 黃桿鉛筆 |
| 代針筆 | 學習鉛筆 |
| 代針筆 | 代針筆 |
+-----------+-----------+
(25 rows)
可以觀察到會出現相同商品的組合.例如 (三角鉛筆,三角鉛筆)
(代針筆,代針筆).
select a.prdct_nme
, b.prdct_nme
from it200117a a
join it200117a b
on (a.id <> b.id);
+-----------+-----------+
| prdct_nme | prdct_nme |
+-----------+-----------+
| 三角鉛筆 | 藍桿鉛筆 |
| 三角鉛筆 | 黃桿鉛筆 |
| 三角鉛筆 | 學習鉛筆 |
| 三角鉛筆 | 代針筆 |
| 藍桿鉛筆 | 三角鉛筆 |
...
| 藍桿鉛筆 | 代針筆 |
...
| 學習鉛筆 | 代針筆 |
| 代針筆 | 三角鉛筆 |
| 代針筆 | 藍桿鉛筆 |
| 代針筆 | 黃桿鉛筆 |
| 代針筆 | 學習鉛筆 |
+-----------+-----------+
(20 rows)
這樣雖然沒有出現相同商品的組合,但是可以觀察到
(三角鉛筆,藍桿鉛筆), (藍桿鉛筆,三角鉛筆)
與
(藍桿鉛筆,代針筆), (代針筆,藍桿鉛筆) 等
順序不同,但是內容一樣的.
若我們想得到所有的組合,
(三角鉛筆,藍桿鉛筆), (藍桿鉛筆,三角鉛筆) 視為相同組合,只要任意一個就好.
一般是id 小的先,這只是一般習慣,非強制.
類似以下的組合
+-----------+-----------+
| prdct_nme | prdct_nme |
+-----------+-----------+
| 三角鉛筆 | 藍桿鉛筆 |
| 三角鉛筆 | 黃桿鉛筆 |
| 三角鉛筆 | 學習鉛筆 |
| 三角鉛筆 | 代針筆 |
| 藍桿鉛筆 | 黃桿鉛筆 |
| 藍桿鉛筆 | 學習鉛筆 |
| 藍桿鉛筆 | 代針筆 |
| 黃桿鉛筆 | 學習鉛筆 |
| 黃桿鉛筆 | 代針筆 |
| 學習鉛筆 | 代針筆 |
+-----------+-----------+
(10 rows)
當然也可以用其他順序,只要所有商品的組合是一樣的就可以了.
可以看到每個商品出現了4次,就是與其他4個商品組合.
如以下,也是一種.
+-----------+-----------+
| prdct_nme | prdct_nme |
+-----------+-----------+
| 藍桿鉛筆 | 三角鉛筆 |
| 黃桿鉛筆 | 三角鉛筆 |
| 黃桿鉛筆 | 藍桿鉛筆 |
| 學習鉛筆 | 三角鉛筆 |
| 學習鉛筆 | 藍桿鉛筆 |
| 學習鉛筆 | 黃桿鉛筆 |
| 代針筆 | 三角鉛筆 |
| 代針筆 | 藍桿鉛筆 |
| 代針筆 | 黃桿鉛筆 |
| 代針筆 | 學習鉛筆 |
+-----------+-----------+
(10 rows)
這裡粗體出包了...
**請問要如何下query? **
SELECT *
FROM ( --利用ROW_NUMBER() 相同資料做排序 只選出排序=1的
SELECT A.idA,A.prdct_nmeA,A.idB,A.prdct_nmeB,A.total
,ROW_NUMBER() OVER(PARTITION BY A.total ORDER BY A.total) AS 排序
FROM (
--相同組合不同位置 id相加一定一樣
select a.id AS idA,a.prdct_nme AS prdct_nmeA
,b.id AS idB, b.prdct_nme AS prdct_nmeB
,(a.id+b.id) as total
from it200117a a
join it200117a b on (a.id <> b.id)
) A
) B
WHERE B.排序 = 1
感謝大大提供題目,藉由這題讓我爬文學到東西 ^_^
以下方式不是我自己想到的邏輯,邏輯來源 :
sql - How to remove same permutations from different mutiple columns - Stack Overflow
因為此範例是自己cross join自己
並且有PK ID
,所以可以使用以下SQL簡單得到結果
select
a.prdct_nme as prdct_nme1
, b.prdct_nme as prdct_nme2
from it200117a a
cross join it200117a b
where a.id < b.id
注意假如是join其他表格,這個做法是不適用的!
select a.prdct_nme, b.prdct_nme
from it200117a a
join it200117a b
on (a.id < b.id);
感覺樓上好很多...
當參加
select a.prdct_nme, b.prdct_nme
from it200117a a
join it200117a b
on a.id != b.id
GROUP BY a.id * b.id
最爛的在這兒啦,叫我倒數第一名~
with temp AS (
(SELECT
prdct_nme,
@a:=@a+1 AS sss,
(select prdct_nme from it200117a where id=@a) prdct_cnme
FROM
it200117a , (SELECT @a:= 1) AS s)
union
(SELECT
prdct_nme,
@b:=@b+1 AS sss,
(select prdct_nme from it200117a where id=@b) prdct_cnme
FROM
it200117a , (SELECT @b:= 2) AS s)
union
(SELECT
prdct_nme,
@c:=@c+1 AS sss,
(select prdct_nme from it200117a where id=@c) prdct_cnme
FROM
it200117a , (SELECT @c:= 3) AS s)
union
(SELECT
prdct_nme,
@d:=@d+1 AS sss,
(select prdct_nme from it200117a where id=@d) prdct_cnme
FROM
it200117a , (SELECT @d:= 4) AS s)
)
select
prdct_nme,
prdct_cnme
from
temp
where
not isnull(concat(prdct_nme,prdct_cnme))
order by
prdct_nme
還有人能比我爛嗎?
其實我的答案已經有人寫出來了。
SELECT a.prdct_nme,b.prdct_nme
FROM `it200117a` AS a
JOIN `it200117a` AS b ON a.id<b.id
所以我來惡搞一個答案
SELECT a.prdct_nme,b.prdct_nme
FROM `it200117a` AS a
JOIN `it200117a` AS b ON a.prdct_nme > b.prdct_nme
其實還可以惡搞更多答案。不過算了。