求用SQL实现一个排列组合的算法题

ifvlr 2018-04-29 07:29:26
原始数据如图一


想得到图二的结果


简单来说,图一是要去做排列组合的基础的数据,基础数据只有1,2,3三个不同的值, 图二是图一通过排列组合后的最简结果,把里面能合并的数据合并,不能合并的数据继续用原始的数据写出来即可。。请问这个要如何实现。
如:
1 1 2 1
1 1 2 3
可以合并为
1 1 2 1,3


1 2 2 1
1 2 2 3
3 2 2 3
3 2 2 1
可以合并为
1,3 2 2 1,3

但是像原始数据
1 3 2 3
就没法和别的数据做排列组合的合并,那么在result表中就继续保留为
1 3 2 3

当然,我这只是部分数据,实际数据很多,可能最终result的结果在算法不同的情况下得到的排列组合方式也不一样,我希望能得到 select count(*) from t_sort_and_comb_result 的结果最小的算法为最优解。
请问这个如何实现。可以用SQL,循环,游标,存储过程等等方法,只要能得到最优的结果。
...全文
2730 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
nayi_224 2018-05-31
  • 打赏
  • 举报
回复
http://www.itpub.net/forum.php?mod=viewthread&tid=2102296 http://www.itpub.net/thread-1851315-1-2.html 好像跟这俩有点像
nayi_224 2018-05-31
  • 打赏
  • 举报
回复
可以递归组合吧。 with tab as ( select '1' a from dual union all select '1,2' from dual union all select '1,3' from dual union all select '1,2,3' from dual union all select '2' from dual union all select '2,3' from dual union all select '3' from dual ), all_result as ( select rownum id, t1.a aa, t2.a bb, t3.a cc, t4.a dd from tab t1, tab t2, tab t3, tab t4) , data1 as ( select 1 data_id, 1 a, 2 b, 3 c, 3 d from dual union all select 2, 2 a, 2 b, 3 c, 3 d from dual union all select 4, 3 a, 1 b, 1 c, 2 d from dual union all select 3, 2 a, 2 b, 3 c, 3 d from dual ), data2 as ( select distinct * from data1) ,result1 as ( select t1.*, t2.*, count(distinct t2.a) over(partition by t1.id) cta, count(distinct t2.b) over(partition by t1.id) ctb, count(distinct t2.c) over(partition by t1.id) ctc, count(distinct t2.d) over(partition by t1.id) ctd, count( t2.a) over(partition by t1.id, t2.a) checkta, count( t2.b) over(partition by t1.id, t2.b) checktb, count( t2.c) over(partition by t1.id, t2.c) checktc, count( t2.d) over(partition by t1.id, t2.d) checktd, (length(t1.aa) + 1) / 2 la, (length(t1.bb) + 1) / 2 lb, (length(t1.cc) + 1) / 2 lc, (length(t1.dd) + 1) / 2 ld from all_result t1, data2 t2 where 1 = 1 and instr(t1.aa, t2.a) > 0 and instr(t1.bb, t2.b) > 0 and instr(t1.cc, t2.c) > 0 and instr(t1.dd, t2.d) > 0 ) ,result2 as ( select * from result1 t1 where 1 = 1 and cta = la and ctb = lb and ctc = lc and ctd = ld and t1.id not in ( select id from result1 v1 where v1.checkta + v1.checktb + v1.checktc + v1.checktd = 4 ) ) ,fin1 as ( select t1.*, count(1) over(partition by t1.id) all_id_max from result2 t1, data2 t2 where 1 = 1 and instr(t1.aa, t2.a) > 0 and instr(t1.bb, t2.b) > 0 and instr(t1.cc, t2.c) > 0 and instr(t1.dd, t2.d) > 0 ), fin2 as ( select t1.*, max(t1.all_id_max) over(partition by t1.data_id) data_max_all_id from fin1 t1 ), clu_fin as ( select distinct t1.id, aa, bb, cc, dd from fin2 t1 where t1.all_id_max = t1.data_max_all_id ) select to_char(t1.data_id) q, to_char(t1.a) w, to_char(t1.b) e, to_char(t1.c) r, to_char(t1.d) t from data2 t1 where t1.data_id not in ( select t2.data_id from clu_fin t1, data2 t2 where 1 = 1 and instr(t1.aa, t2.a) > 0 and instr(t1.bb, t2.b) > 0 and instr(t1.cc, t2.c) > 0 and instr(t1.dd, t2.d) > 0) union all select to_char(t2.id), to_char(t2.aa), to_char(t2.bb), to_char(t2.cc), to_char(t2.dd) from clu_fin t2 ;
ifvlr 2018-05-09
  • 打赏
  • 举报
回复
另外,还有一个拆分排列组合需求,如

拆分成

同样还是 出现组合的数据可能出现在任何字段。 可能有一个字段是组合的,也可能是多个字段组合的。请问有什么号办法呢?






引用 1 楼 wmxcn2000 的回复:
楼主研究下 listagg 这个函数,真好适合你现在的需求。

大概如下

select a,b,c,
litangg(d,',') within group(order by d)
from t
group by a,b,c


-- 注意:拼接后的长度,不能超过4000。



引用 2 楼 baidu_36457652 的回复:
这个合并用 listagg可以达到,但是你这排列组合方式的方式达到你的效果估计难了
ifvlr 2018-05-02
  • 打赏
  • 举报
回复
引用 2 楼 baidu_36457652 的回复:
这个合并用 listagg可以达到,但是你这排列组合方式的方式达到你的效果估计难了
是的,可能需要多层嵌套,按照一楼的解法,每次组合一个字段,把这个结果继续拿去做嵌套查询,有多少列就嵌套多少次,那样可能能得到一个合并后的结果,但并不一定是最优结果。
ifvlr 2018-05-02
  • 打赏
  • 举报
回复
引用 1 楼 wmxcn2000 的回复:
楼主研究下 listagg 这个函数,真好适合你现在的需求。 大概如下 select a,b,c, litangg(d,',') within group(order by d) from t group by a,b,c -- 注意:拼接后的长度,不能超过4000。
您说的这种方式只考虑了一个字段,而我的需求不只是D列这一个字段需要组合,而是A,B,C列均有存在组合的可能,如t_sort_and_comb_result表中的第三条记录,第三条记录就是由4条记录合并而来的。。当然实际的数据,是有十几个列,几千行数据的合并,每一个列都可能存在一个or多个组合,把能合并的数据合并,不能合并的数据保持原样。得到的结果条数最少为最优解。 您说的这种方式和我写group by 然后用wm_concat方式合并感觉差不多哦~ 我在网上找了下,感觉listagg并不能直接解决我的问题。 另外 litangg--> listagg
卖水果的net 2018-04-30
  • 打赏
  • 举报
回复
楼主研究下 listagg 这个函数,真好适合你现在的需求。 大概如下 select a,b,c, litangg(d,',') within group(order by d) from t group by a,b,c -- 注意:拼接后的长度,不能超过4000。
  • 打赏
  • 举报
回复
这个合并用 listagg可以达到,但是你这排列组合方式的方式达到你的效果估计难了
随着通信电子技术的迅速发展,信息技术给家居行业产生了深远的影响,家居环境的智能化监控已经成为智能家居的一个重要的发展方向。人们逐渐对自己的生活提出一种更高的要求,他们需要一种智能化、可交互,并且融合现代创新科技的产品来改善他们的生活环境,使他们生活更加安全、舒适、便捷、智能。本文根据智能家居的发展背景和研究现状,并且从实用性和可行性角度出发,研究设计了一种基于STM32单片机的智能家居系统。该系统由一个多功能综合的技术系统组成,各个多功能子系统间具有协同配合能力。基于STM32单片机实现的功能子系统包括:智能温度检测,智能湿度检测,智能烟雾/火灾检测智能检测,无线传输,人机交互机构,风扇调节,报警模块。 整个系统分为前端51单片机采集板和后端STM32单片机接收板。 采集板使用DHT11温湿度传感器、MQ烟雾传感器完成室内家居环境的采集。然后通过nRFL24L01将采集到的数据发送给后端。接收板使用LCD1602完成数据显示、使用蜂鸣器模块报警,使用风扇驱动模块调节室内家居环境。本文完成了智能家居控制系统前端、后端软硬件的设计,使用Altium designer绘制了电路原理图,使用Keil C完成了51单片机和STM32单片机的编程与调试。 最后,对本文设计的基于STM32的智能家居控制系统进行部署调试。试验结果表明,该系统可成功应用在智能家居环境检测调节和火灾安全防护的领域,可提高家居生活智能化水平。

3,499

社区成员

发帖
与我相关
我的任务
社区描述
Oracle 高级技术相关讨论专区
社区管理员
  • 高级技术社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧