ITPUB论坛-中国最专业的IT技术社区

 找回密码
 注册
查看: 20574|回复: 67

[精华] 求反GROUP BY的写法

[复制链接]
论坛徽章:
3
鲜花蛋
日期:2011-07-05 17:12:112012新春纪念徽章
日期:2012-01-04 11:54:46优秀写手
日期:2013-12-18 09:29:13
发表于 2011-10-26 22:48 | 显示全部楼层 |阅读模式
比如有一张表TEST,GROUP BY后的数据如下:
NAME   CNT
A         2
B         4
C         1
..        ..
CNT为出现的次数,现在要反过来写,需要得出数据
A
A
B
B
B
B
C
请问一条SQL怎么写,而且需要考虑效率问题,不要去笛卡儿积
论坛徽章:
496
目光如炬
日期:2015-11-22 22:00:00秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21探花
日期:2016-01-06 14:11:18进士
日期:2016-01-06 14:11:18
发表于 2011-10-26 23:10 | 显示全部楼层
WITH data AS (
SELECT  'A' name, 2 cnt FROM DUAL
UNION ALL SELECT 'B', 4 FROM DUAL
UNION ALL SELECT 'C', 1 FROM DUAL
)
SELECT name
  FROM data
CONNECT BY name=PRIOR name AND LEVEL<=cnt AND PRIOR SYS_GUID() IS NOT NULL;

使用道具 举报

回复
论坛徽章:
3
鲜花蛋
日期:2011-07-05 17:12:112012新春纪念徽章
日期:2012-01-04 11:54:46优秀写手
日期:2013-12-18 09:29:13
 楼主| 发表于 2011-10-26 23:24 | 显示全部楼层
newkid 发表于 2011-10-26 23:10
WITH data AS (
SELECT  'A' name, 2 cnt FROM DUAL
UNION ALL SELECT 'B', 4 FROM DUAL

学到了,谢谢,问题终于可以解决了

使用道具 举报

回复
招聘 : 系统分析师
论坛徽章:
483
马上有车
日期:2014-02-18 16:41:11itpub13周年纪念徽章
日期:2014-09-28 10:55:55itpub13周年纪念徽章
日期:2014-09-29 01:14:14itpub13周年纪念徽章
日期:2014-10-08 15:15:25itpub13周年纪念徽章
日期:2014-10-08 15:15:25马上有对象
日期:2014-10-12 11:58:40马上有车
日期:2014-11-16 17:11:29慢羊羊
日期:2015-02-09 17:04:38沸羊羊
日期:2015-03-04 14:43:432015年新春福章
日期:2015-03-06 11:57:31
发表于 2011-10-26 23:41 | 显示全部楼层
本帖最后由 〇〇 于 2011-10-27 13:21 编辑

我的blog上有 http://lastwinner.itpub.net/post/7102/46962
由于历史原因,blog上的关于SQL改进的评论被删除了,改进的sql效率跟newkid的应该差不多

当然,你直接参考newkid的办法就好
不过,我还是建议你采用hmxxyy的方法,这里的思路可以应用在更广泛的地方

  1. Simulate a loop in SQL【By hmxxyy】
  2. ===========================================================
  3. Simulate a loop in SQL【By hmxxyy】
  4. 作者: lastwinner(http://lastwinner.itpub.net)
  5. 发表于: 2005.11.26 21:23
  6. 分类: Oracle
  7. 出处: http://lastwinner.itpub.net/post/7102/46962
  8. ---------------------------------------------------------------

  9. SQL> select * from x;

  10. C1 C2
  11. ---------- ----------
  12. 11111 1
  13. 22222 2
  14. 33333 3
  15. 44444 4

  16. SQL> create table y (c1 number);

  17. Table created.

  18. SQL> insert into y
  19. 2 select a.c1 from x a,
  20. 3 (
  21. 4 select rownum rn from (select max(c2) maxlevel from x) a connect by 1=1 and level <=
  22. 5 maxlevel) b
  23. 6 where a.c2 >= rn
  24. 7 order by c1
  25. 8 /

  26. 10 rows created.

  27. SQL> select * from y;

  28. C1
  29. ----------
  30. 11111
  31. 22222
  32. 22222
  33. 33333
  34. 33333
  35. 33333
  36. 44444
  37. 44444
  38. 44444
  39. 44444
  40. http://blog.itpub.net/post/4791/27191


  41. 偶的方法:
  42. SQL> create table loopx(c1 varchar2(20),c2 number(3));

  43. 表已创建。

  44. SQL> insert into loopx select lpad(rownum,5,rownum),rownum from dual connect by
  45. rownum<5;

  46. 已创建4行。

  47. SQL> select * from loopx;

  48. C1 C2
  49. -------------------- ----------
  50. 11111 1
  51. 22222 2
  52. 33333 3
  53. 44444 4

  54. SQL> select distinct a.c1,level from loopx a connect by level<=c2;

  55. C1 LEVEL
  56. -------------------- ----------
  57. 11111 1
  58. 22222 1
  59. 22222 2
  60. 33333 1
  61. 33333 2
  62. 33333 3
  63. 44444 1
  64. 44444 2
  65. 44444 3
  66. 44444 4

  67. 已选择10行。

  68. 不明白他为什么要写那么复杂,不过我用了distinct,过滤了大量的记录,也许这种方法效率低吧

  69. lastwinner 发表于:2005.11.26 21:23 ::分类: ( Oracle ) ::阅读:(1323次) :: 评论 (0)

复制代码

使用道具 举报

回复
论坛徽章:
496
目光如炬
日期:2015-11-22 22:00:00秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21探花
日期:2016-01-06 14:11:18进士
日期:2016-01-06 14:11:18
发表于 2011-10-26 23:45 | 显示全部楼层
看了你的博客,你的方法不行的,你的CONNECT BY里面没有前后C1要相等的限制,中间结果会很大(假如原来就是个大表)。

使用道具 举报

回复
招聘 : 系统分析师
论坛徽章:
483
马上有车
日期:2014-02-18 16:41:11itpub13周年纪念徽章
日期:2014-09-28 10:55:55itpub13周年纪念徽章
日期:2014-09-29 01:14:14itpub13周年纪念徽章
日期:2014-10-08 15:15:25itpub13周年纪念徽章
日期:2014-10-08 15:15:25马上有对象
日期:2014-10-12 11:58:40马上有车
日期:2014-11-16 17:11:29慢羊羊
日期:2015-02-09 17:04:38沸羊羊
日期:2015-03-04 14:43:432015年新春福章
日期:2015-03-06 11:57:31
发表于 2011-10-26 23:48 | 显示全部楼层
newkid 发表于 2011-10-26 23:45
看了你的博客,你的方法不行的,你的CONNECT BY里面没有前后C1要相等的限制,中间结果会很大(假如原来就是 ...

都怪老虎,当初删垃圾评论,结果只要含有链接的评论都被删除了
我的改进是放在评论里的,当时带有itpub的链接,也一并被删除了

使用道具 举报

回复
论坛徽章:
496
目光如炬
日期:2015-11-22 22:00:00秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21探花
日期:2016-01-06 14:11:18进士
日期:2016-01-06 14:11:18
发表于 2011-10-26 23:49 | 显示全部楼层
再来一个:
WITH data AS (
SELECT  'A' name, 2 cnt FROM DUAL
UNION ALL SELECT 'B', 4 FROM DUAL
UNION ALL SELECT 'C', 1 FROM DUAL
)
SELECT name
  FROM data
      ,TABLE( CAST( MULTISET( SELECT 1 FROM DUAL CONNECT BY LEVEL <= data.cnt ) AS SYS.ODCINUMBERLIST)) ;

我还试图用MODEL但没有成功。

其实我也赞同hmxxyy的方法。

使用道具 举报

回复
论坛徽章:
496
目光如炬
日期:2015-11-22 22:00:00秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21探花
日期:2016-01-06 14:11:18进士
日期:2016-01-06 14:11:18
发表于 2011-10-26 23:49 | 显示全部楼层
lastwinner 发表于 2011-10-26 23:48
都怪老虎,当初删垃圾评论,结果只要含有链接的评论都被删除了
我的改进是放在评论里的,当时带有i ...

哇K, 链接到ITPUB也不行,老虎真是大义灭亲。

使用道具 举报

回复
论坛徽章:
1088
金色在线徽章
日期:2007-04-25 04:02:08金色在线徽章
日期:2007-06-29 04:02:43金色在线徽章
日期:2007-03-11 04:02:02在线时间
日期:2007-04-11 04:01:02在线时间
日期:2007-04-12 04:01:02在线时间
日期:2007-03-07 04:01:022008版在线时间
日期:2010-05-01 00:01:152008版在线时间
日期:2011-05-01 00:01:342008版在线时间
日期:2008-06-03 11:59:43ITPUB年度最佳技术原创精华奖
日期:2013-03-22 13:18:30
发表于 2011-10-27 00:46 | 显示全部楼层
以前他们用xml搞的
SQL> WITH data AS (
  2  SELECT  'A' name, 2 cnt FROM DUAL
  3  UNION ALL SELECT 'B', 4 FROM DUAL
  4  UNION ALL SELECT 'C', 1 FROM DUAL
  5  )
  6  SELECT NAME, x.num AS num
  7    FROM data,
  8         xmltable('1 to xs:integer($n)' passing cnt AS "n" columns num FOR
  9                  ordinality) x
10  ORDER BY 1, 2;

NAME        NUM
---- ----------
A            1
A            2
B            1
B            2
B            3
B            4
C            1

7 rows selected

使用道具 举报

回复
论坛徽章:
496
目光如炬
日期:2015-11-22 22:00:00秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21秀才
日期:2016-01-06 14:10:21探花
日期:2016-01-06 14:11:18进士
日期:2016-01-06 14:11:18
发表于 2011-10-27 02:33 | 显示全部楼层
终于把MODEL搞出来了:
WITH data AS (
SELECT  'A' name, 2 cnt FROM DUAL
UNION ALL SELECT 'B', 4 FROM DUAL
UNION ALL SELECT 'C', 1 FROM DUAL
)
SELECT name
  FROM data
MODEL
PARTITION BY (name)
DIMENSION BY (1 n)
MEASURES (cnt)
RULES
ITERATE (100) UNTIL (ITERATION_NUMBER>=cnt[1]-1)
  (
     cnt[ITERATION_NUMBER+1]=cnt[1]
  )
ORDER BY 1;
  

使用道具 举报

回复

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

本版积分规则

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