楼主: 最闪亮滴星

[SQL] 背包问题-优美的SQL讨论

[复制链接]
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
11#
发表于 2023-3-14 02:56 | 只看该作者

领导真幽默,你还需要学什么呢? 这里现在就是我跳广场舞的地方。

使用道具 举报

回复
论坛徽章:
0
12#
 楼主| 发表于 2023-3-14 12:29 | 只看该作者
jlandzpa 发表于 2023-3-12 20:01
看到“ > 150000” 的条件 ,就知道语句不具备普适性。

大佬好,我这纯粹偷工减料的

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
13#
发表于 2023-3-15 00:33 | 只看该作者
最闪亮滴星 发表于 2023-3-14 12:29
大佬好,我这纯粹偷工减料的

想通了没有?这个代码要如何修改?

使用道具 举报

回复
论坛徽章:
0
14#
发表于 2023-3-16 08:34 | 只看该作者
It can be two cases, perfect grouping and imperfect grouping.  

For example, 70 in total is put into 7 groups (each 10 exactly).  For this perfect grouping, one can find 2 groups first, one has 30 and one has 40.  For group with 30, find another two, 10 and 20.  And for group with 40, find all possible 20s which in turn finds all possible 10s (each step dividing into two groups).  Cross join all 10s from 30 and 40 will generate at least one valid combination.

For imperfect grouping, I would use partial random evolution approach first to get a combination with smaller deviations and use it to filter out all worse combinations as early as possible in brutal force process.

One can play with a series of different numbers to sense the advantages of doing so.

使用道具 举报

回复
论坛徽章:
0
15#
发表于 2023-3-17 15:03 | 只看该作者
本人不才,用pg语法写一个暴力解
  1. WITH RECURSIVE T1 AS (
  2.     SELECT datapath
  3.          , bytes::INT
  4.          , ROW_NUMBER()OVER(ORDER BY datapath) AS order1
  5.          , COUNT(*)OVER() AS all_datapath
  6.     FROM   schema1.testpath2
  7. ),
  8. --递归寻找所有组合,order1用于递归的依据,order2用于记录起始位置的order,方便用于下一次循环
  9. --all_datapath记录文件总数
  10. T2 AS (
  11.     SELECT ARRAY[datapath] AS datapath
  12.          , bytes
  13.          , order1
  14.          , order1 AS order2
  15.          , all_datapath
  16.     FROM   T1
  17.        
  18.       UNION ALL
  19.           
  20.     SELECT T2.datapath||T1.datapath
  21.          , T2.bytes::INT + T1.bytes::INT
  22.          , T1.order1
  23.          , T2.order2
  24.          , T2.all_datapath
  25.     FROM   T2
  26.     JOIN   T1
  27.     ON   ( T1.order1 > T2.order1  )
  28. ),
  29. --只取出所有<=16T的组合
  30. T3 AS (
  31.     SELECT datapath
  32.          , ARRAY[bytes] AS bytes
  33.          , all_datapath
  34.          , order2
  35.     FROM   T2
  36.     WHERE  bytes <= 160000
  37. ),
  38. --此处逻辑理论上有更优方法,目前会产生很多无用的递归结果
  39. T4 AS (
  40.     SELECT datapath
  41.          , datapath::TEXT AS GROUP1
  42.          , bytes
  43.          , all_datapath
  44.          , order2
  45.     FROM   T3
  46.     WHERE  order2 = 1
  47.        
  48.       UNION ALL
  49.        
  50.     SELECT T3.datapath||T4.datapath
  51.          , T4.GROUP1||T3.datapath::TEXT
  52.          , T4.bytes||T3.bytes
  53.          , T4.all_datapath
  54.          , T3.order2
  55.     FROM   T4
  56.     JOIN   T3
  57.     ON   ( T3.order2 > T4.order2
  58.        AND NOT T3.datapath && T4.datapath
  59.     )
  60. )
  61. SELECT group1
  62.      , bytes
  63. FROM   T4
  64. WHERE  ARRAY_LENGTH(datapath, 1) = all_datapath
  65. AND    ARRAY_LENGTH(bytes,1) =
  66. (   
  67.     SELECT MIN(ARRAY_LENGTH(bytes,1))
  68.     FROM   T4
  69.     WHERE  ARRAY_LENGTH(datapath, 1) = all_datapath
  70. );
复制代码

按照楼主的数据跑的话**解法大概有24种
查询结果说我有非法字符,传不上来

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
16#
发表于 2023-3-18 00:15 | 只看该作者
T3 可以合并到T2, 使得递归效率更高。
PG的数组操作可以用&&,比我用ORACLE的BITAND方便。

使用道具 举报

回复
论坛徽章:
0
17#
发表于 2023-3-21 12:33 | 只看该作者
最闪亮滴星 发表于 2023-3-10 16:00
测试表create table  testpath2 as (select '/data/'as datas ,'file1' as datapath ,'9999' as bytes from ...

If it can be an imperfect grouping for real request.  My favor is (do not have link at hand) as below.  Determine how many groups needed.  Order all values in sequence.  Pick biggest n (number of groups) values and put into each group first.  Then put each following value into the group with minimum sum value at each step until all values are processed.  This approach is quite efficient for data distribution with a few large bills and many coins (or simlar to filling tanks with a few rocks and much sand).
Quickly write one below to demonstrate it.

SQL> /
Enter value for gno: 5
Enter value for rowcnt: 10
old   1: with t0 as (select &gno gno, &rowcnt rowcnt from dual
new   1: with t0 as (select 5 gno, 10 rowcnt from dual

PATH_BY_ID                                         GROUP_VALUE
-------------------------------------------------- -----------
1,10                                                        11
5,6                                                         11
2,9                                                         11
4,7                                                         11
3,8                                                         11

SQL> /
Enter value for gno: 5
Enter value for rowcnt: 20
old   1: with t0 as (select &gno gno, &rowcnt rowcnt from dual
new   1: with t0 as (select 5 gno, 20 rowcnt from dual

PATH_BY_ID                                         GROUP_VALUE
-------------------------------------------------- -----------
3,8,11,20                                                   42
4,7,15,16                                                   42
2,9,12,19                                                   42
1,10,14,17                                                  42
5,6,13,18                                                   42

SQL>
SQL>
SQL> /
Enter value for gno: 5
Enter value for rowcnt: 40
old   1: with t0 as (select &gno gno, &rowcnt rowcnt from dual
new   1: with t0 as (select 5 gno, 40 rowcnt from dual

PATH_BY_ID                                         GROUP_VALUE
-------------------------------------------------- -----------
4,7,15,16,23,28,31,40                                      164
3,8,11,20,24,27,35,36                                      164
2,9,12,19,22,29,32,39                                      164
5,6,13,18,21,30,34,37                                      164
1,10,14,17,25,26,33,38                                     164

SQL>
SQL>



==========================================================

with t0 as (select &gno gno, &rowcnt rowcnt from dual
), t as (select rownum val from t0 connect by rownum<=rowcnt
), tt as (select val, row_number() over (order by val desc) id from t
), tmp (rn, path, vals, lrn) as (
select 1, to_char(id), val, id from tt, t0 where id <=t0.gno
union all
select rn+1, path||decode(id, null, null, ','||id), vals+nvl(val, 0),
row_number() over (order by  vals+nvl(val, 0) desc)
from tmp a, tt, t0
where rn+decode(lrn, gno, lrn) = tt.id (+)
and rn<=rowcnt-gno
)
select path path_by_id, vals group_value from tmp, t0
where rn=rowcnt-gno+1
/



使用道具 举报

回复
论坛徽章:
0
18#
发表于 2023-3-21 12:55 | 只看该作者
I would think it is possible to write a sql for partial random evolution process for imperfect grouping although it may look ugly.  Basically pick out a value from the group with maximum sum value and put it into the group with minimum sum value.  Loop enough time to output the best grouping result (based on deviation or whatever critieria).  One can pick several random initial group setup and parallelly the process for better results.  According to statistics (probability), if one runs enough times, the best result can probably be achieved.

For perfect grouping, a single recursive function is enough (hard to do it in sql).  using input parameter for array or string with all values first, process to get ONE group and then exclude the values in this group and input the resulting array or string into the recursive function for next group picking until the last group is processed.  I do have a demonstration to argue why doing so which needs some clean up before posting it.

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
19#
发表于 2023-3-21 22:13 | 只看该作者
jihuyao 发表于 2023-3-21 12:33
If it can be an imperfect grouping for real request.  My favor is (do not have link at hand) as belo ...

你这方法也太简陋了,只是轮流往上叠加,甚至都没有检查是否超过限额。

使用道具 举报

回复
论坛徽章:
0
20#
发表于 2023-3-25 10:52 | 只看该作者
newkid 发表于 2023-3-21 22:13
你这方法也太简陋了,只是轮流往上叠加,甚至都没有检查是否超过限额。

It does not hurt to try this simple way first quickly for imperfect grouping.  If it meets the requirement why bother other ways?

I am not sure about the meaning of upper limit.  If one group has aleady enough sum values above theoretical average, it will not be possible to be the group with minimum sum value and therefore any following smaller values will be added to other groups.

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表