查看: 15976|回复: 43

【每周一议】干货讨论 如何合并两个查询的结果集的数据

[复制链接]
认证徽章
论坛徽章:
24
技术图书徽章
日期:2013-08-16 14:31:52问答徽章
日期:2013-11-04 08:53:14目光如炬
日期:2013-12-23 06:00:11目光如炬
日期:2013-12-30 06:00:11明星写手
日期:2014-02-22 06:00:12马上有钱
日期:2014-03-31 14:09:05沸羊羊
日期:2015-05-20 12:42:59秀才
日期:2015-06-24 13:05:36秀才
日期:2015-07-13 09:48:14
发表于 2012-11-7 09:31 | 显示全部楼层 |阅读模式
讨论背景:

(新用户)通过表A获取的记录集,如下:

1   2012-11-1
3   2012-11-2
8   2012-11-5

(老用户)通过表B获取的记录集,如下:

5   2012-11-1
3   2012-11-2

我想将这两个结果集合并为一个结果集。显示的结果如下:

日期         新用户    老用户
2012-11-1     1          5
2012-11-2     3          3
2012-11-5     8          0

如果不能合并。只能在查找注册用户的语句循环中。每次都要通过当前的日期来再做一次查询(统计老用户)。这样的效率也太低。

讨论话题:如何合并两个查询的结果集的数据?

讨论时间:2012.11.7-2012.11.21

讨论奖励:针对以上问题跟帖回答,我们会在讨论结束后,随机抽选5名讨论最积极的会员赠送《MySQL技术内幕:InnoDB存储引擎》作为奖励。
1.jpg
认证徽章
论坛徽章:
82
2013年新春福章
日期:2013-02-25 14:51:24奥运会纪念徽章:排球
日期:2013-04-11 18:16:37奥运会纪念徽章:曲棍球
日期:2013-04-11 18:16:47奥运会纪念徽章:垒球
日期:2013-04-27 15:03:48奥运会纪念徽章:跳水
日期:2013-04-27 15:04:27奥运会纪念徽章:举重
日期:2013-04-27 15:04:27奥运会纪念徽章:田径
日期:2013-04-27 15:04:27奥运会纪念徽章:赛艇
日期:2013-04-27 15:04:27奥运会纪念徽章:垒球
日期:2013-04-27 15:04:27咸鸭蛋
日期:2013-03-24 21:25:32
发表于 2012-11-7 10:25 | 显示全部楼层
oracle 11g下实测
  1. CREATE TABLE A
  2. (
  3.     ID NUMBER(4),
  4.     MyDate DATE
  5. );
  6. INSERT INTO A VALUES(1, to_date('2012-11-01', 'YYYY-MM-DD'));
  7. INSERT INTO A VALUES(3, to_date('2012-11-02', 'YYYY-MM-DD'));
  8. INSERT INTO A VALUES(8, to_date('2012-11-05', 'YYYY-MM-DD'));

  9. CREATE TABLE B
  10. (
  11.     ID NUMBER(4),
  12.     MyDate DATE
  13. );

  14. INSERT INTO B VALUES(5, to_date('2012-11-01', 'YYYY-MM-DD'));
  15. INSERT INTO B VALUES(3, to_date('2012-11-02', 'YYYY-MM-DD'));


  16. SELECT MyDate AS 日期, nvl(A.ID, 0) AS 新用户, nvl(B.ID, 0) AS 老用户
  17. FROM A FULL OUTER JOIN B
  18. USING (MyDate);
复制代码
01.gif

使用道具 举报

回复
认证徽章
论坛徽章:
25
奥运会纪念徽章:射击
日期:2013-01-28 09:12:182014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-03-20 16:13:24马上有房
日期:2014-03-20 16:14:11马上有钱
日期:2014-03-20 16:14:11马上有对象
日期:2014-03-20 16:14:11马上加薪
日期:2014-03-20 16:14:11喜羊羊
日期:2015-04-09 18:46:34秀才
日期:2016-03-24 09:20:52
发表于 2012-11-7 11:37 | 显示全部楼层
本帖最后由 jimn1982 于 2012-11-7 11:38 编辑

没有看清楚本帖的主题啊。
如何合并两个查询的结果集的数据?
oracle已经提供了很多方法。
union
说明:获得两个结果集的合并,并自动删除重复行,而且会以第一列的结果进行排序

union all
说明:获得两个结果的合并集,但不会自动去掉重复行,并且不会对结果进行排序

intersect
说明:获得两个结果集合的交集,只会显示两个结果集合中同时存在的数据并且会以第一列的结果进行排序

minus
说明:获得两个结果集合的差集,只会显示在第一个结果集中存在但第二个结果集中不存在的数据,并且会以第一列结果进行排序
通俗的说是第一个减去第二个中的数据

对于以上四种方法对版主的需求都满足不了。版主应该用的是连接(左右)而已。

使用道具 举报

回复
论坛徽章:
9
蛋疼蛋
日期:2011-10-18 11:00:17ITPUB十周年纪念徽章
日期:2011-11-01 16:25:51蜘蛛蛋
日期:2011-11-09 13:48:06迷宫蛋
日期:2011-11-24 10:38:342012新春纪念徽章
日期:2012-01-04 11:56:44蜘蛛蛋
日期:2013-07-12 21:52:36凯迪拉克
日期:2013-12-12 09:53:072014年新春福章
日期:2014-02-18 16:44:08马上有对象
日期:2014-02-18 16:44:08
发表于 2012-11-7 12:47 | 显示全部楼层
大家都发出了oracle的,那我发一个mysql版的吧,mysql没有full out join

mysql> select * from newUser;
+---------------------+------+
| dt                  | num  |
+---------------------+------+
| 2012-11-01 00:00:00 |    1 |
| 2012-11-02 00:00:00 |    3 |
| 2012-11-05 00:00:00 |    8 |
+---------------------+------+
3 rows in set (0.00 sec)

mysql> select * from oldUser;
+---------------------+------+
| dt                  | num  |
+---------------------+------+
| 2012-11-01 00:00:00 |    5 |
| 2012-11-02 00:00:00 |    3 |
+---------------------+------+
2 rows in set (0.00 sec)

mysql> select a.dt,a.num new_num,ifnull(b.num,0) old_num from newUser a left join oldUser b on a.dt=b.dt union all select a.dt,a.num new_num,ifnull(b.num,0) old_num from newUser b join oldUser a on a.dt=b.dt  where b.dt is null;
+---------------------+---------+---------+
| dt                  | new_num | old_num |
+---------------------+---------+---------+
| 2012-11-01 00:00:00 |       1 |       5 |
| 2012-11-02 00:00:00 |       3 |       3 |
| 2012-11-05 00:00:00 |       8 |       0 |
+---------------------+---------+---------+
3 rows in set (0.00 sec)


使用道具 举报

回复
论坛徽章:
401
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
发表于 2012-11-7 13:24 | 显示全部楼层

  1. [oracle@redflag11012501 home]$ mysql -uroot
  2. mysql: Unknown OS character set 'GB18030'.
  3. mysql: Switching to the default character set 'latin1'.
  4. Welcome to the MySQL monitor.  Commands end with ; or \g.
  5. Your MySQL connection id is 1
  6. Server version: 5.5.13-log MySQL Community Server (GPL)

  7. Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.

  8. Oracle is a registered trademark of Oracle Corporation and/or its
  9. affiliates. Other names may be trademarks of their respective
  10. owners.

  11. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

  12. mysql> create table ou (dt date, uid int);
  13. ERROR 1046 (3D000): No database selected
  14. mysql> use test
  15. Database changed
  16. mysql> create table ou (dt date, uid int);
  17. Query OK, 0 rows affected (0.02 sec)

  18. mysql> create table nu (dt date, uid int);
  19. Query OK, 0 rows affected (0.01 sec)

  20. mysql> insert into ou values(date' 2012-11-1
  21.     '> ',1);
  22. Query OK, 1 row affected (0.01 sec)

  23. mysql> insert into ou values(date' 2012-11-2
  24. ',3);
  25. Query OK, 1 row affected (0.01 sec)

  26. mysql> insert into ou values(date' 2012-11-5
  27. ',8);
  28. Query OK, 1 row affected (0.00 sec)

  29. mysql> insert into nu values(date' 2012-11-1
  30. ',5);
  31. Query OK, 1 row affected (0.00 sec)

  32. mysql> insert into nu values(date' 2012-11-2
  33. ',3);
  34. Query OK, 1 row affected (0.00 sec)

  35. mysql> select * from ou;
  36. +------------+------+
  37. | dt         | uid  |
  38. +------------+------+
  39. | 2012-11-01 |    1 |
  40. | 2012-11-02 |    3 |
  41. | 2012-11-05 |    8 |
  42. +------------+------+
  43. 3 rows in set (0.02 sec)

  44. mysql> select * from nu;
  45. +------------+------+
  46. | dt         | uid  |
  47. +------------+------+
  48. | 2012-11-01 |    5 |
  49. | 2012-11-02 |    3 |
  50. +------------+------+
  51. 2 rows in set (0.00 sec)

  52. mysql> select o.dt,ou.uid,nu.uid from(select dt from ou union select dt from nu)o left join ou using(dt) left join nu using(dt);
  53. +------------+------+------+
  54. | dt         | uid  | uid  |
  55. +------------+------+------+
  56. | 2012-11-01 |    1 |    5 |
  57. | 2012-11-02 |    3 |    3 |
  58. | 2012-11-05 |    8 | NULL |
  59. +------------+------+------+
  60. 3 rows in set (0.00 sec)

  61. mysql> select o.dt,ifnull(ou.uid,0)newu,ifnull(nu.uid,0)oldu from(select dt from ou union select dt from nu)o left join ou using(dt) left join nu using(dt);
  62. +------------+------+------+
  63. | dt         | newu | oldu |
  64. +------------+------+------+
  65. | 2012-11-01 |    1 |    5 |
  66. | 2012-11-02 |    3 |    3 |
  67. | 2012-11-05 |    8 |    0 |
  68. +------------+------+------+
  69. 3 rows in set (0.01 sec)

  70. mysql>
复制代码

使用道具 举报

回复
论坛徽章:
15
生肖徽章2007版:猪
日期:2009-03-11 15:09:30优秀写手
日期:2013-12-18 09:29:11比亚迪
日期:2013-08-28 12:44:17复活蛋
日期:2013-06-19 15:03:392013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:15奥运会纪念徽章:手球
日期:2012-08-28 17:54:31奥运会纪念徽章:柔道
日期:2012-08-14 16:26:23咸鸭蛋
日期:2012-08-14 16:26:232010广州亚运会纪念徽章:射击
日期:2012-08-14 16:26:23
发表于 2012-11-7 15:40 | 显示全部楼层
我来一个SQL Server 2012 的:
  1. create table a(
  2.   id  int,
  3.   Mydate Date
  4. )
  5. insert into a
  6. select 1,'2012-11-1' union all
  7. select 3,'2012-11-2' union all
  8. select 8,'2012-11-5'

  9. create table b(
  10.   id  int,
  11.   Mydate Date
  12. )
  13. insert into b
  14. select 5,'2012-11-1' union all
  15. select 3,'2012-11-2'

  16. ;with cte as(
  17.   select *,1 Num from a
  18.   union all
  19.   select *, 2 Num from b
  20. )
  21. select MyDate,
  22.        max(case Num when 1 then id else 0 end) new_user,
  23.            max(case Num when 2 then id else 0 end) old_user
  24. from cte
  25. group by myDate
复制代码

使用道具 举报

回复
论坛徽章:
1
2013年新春福章
日期:2013-02-25 14:51:24
发表于 2012-11-8 10:58 | 显示全部楼层
LuiseDalian 发表于 2012-11-7 10:25
oracle 11g下实测

就3楼兄弟的表结构,提供mysql 版本笨方法2个:
法1:
SELECT tmp.newdate,SUM(IF(tmp.flag=1,tmp.newid,0)),SUM(IF(tmp.flag=2,tmp.newid,0))
FROM(
SELECT A.mydate AS newdate,A.id AS newid,1 AS flag FROM A
UNION ALL
SELECT B.mydate AS newdate,B.id AS newid,2 AS flag FROM B
) as tmp
GROUP BY tmp.newdate;

法2:
SELECT A.mydate,A.id,IF(B.id is NULL ,0,B.id )
FROM A LEFT  JOIN B ON A.mydate=B.mydate
UNION
SELECT B.mydate,IF(A.id is NULL ,0,A.id ),B.id
FROM B LEFT  JOIN A ON A.mydate=B.mydate
;

使用道具 举报

回复
论坛徽章:
0
发表于 2012-11-8 17:11 | 显示全部楼层
ORACLE 9i 调试通过。

create table TEMP1
(
  RDATA DATE,
  RUSER VARCHAR2(10)
);
create table TEMP2
(
  RDATA DATE,
  RUSER VARCHAR2(10)
);


insert into TEMP1 (RDATA, RUSER)
values (to_date('05-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('02-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('02-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('02-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('01-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('05-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('05-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('05-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('05-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('05-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('05-11-2012', 'dd-mm-yyyy'), 'NEW');
insert into TEMP1 (RDATA, RUSER)
values (to_date('05-11-2012', 'dd-mm-yyyy'), 'NEW');
commit;

insert into TEMP2 (RDATA, RUSER)
values (to_date('01-11-2012', 'dd-mm-yyyy'), 'OLD');
insert into TEMP2 (RDATA, RUSER)
values (to_date('01-11-2012', 'dd-mm-yyyy'), 'OLD');
insert into TEMP2 (RDATA, RUSER)
values (to_date('01-11-2012', 'dd-mm-yyyy'), 'OLD');
insert into TEMP2 (RDATA, RUSER)
values (to_date('01-11-2012', 'dd-mm-yyyy'), 'OLD');
insert into TEMP2 (RDATA, RUSER)
values (to_date('01-11-2012', 'dd-mm-yyyy'), 'OLD');
insert into TEMP2 (RDATA, RUSER)
values (to_date('02-11-2012', 'dd-mm-yyyy'), 'OLD');
insert into TEMP2 (RDATA, RUSER)
values (to_date('02-11-2012', 'dd-mm-yyyy'), 'OLD');
insert into TEMP2 (RDATA, RUSER)
values (to_date('02-11-2012', 'dd-mm-yyyy'), 'OLD');
commit;

SQL> select  new,a.rdata,b.rdata  from
  2  (select rdata as new,count(*)rdata from temp1 group by rdata ) a,
  3  (select rdata as old,count(*)rdata from temp2 group by rdata ) b
  4  where   a.new=b.old(+)
  5  ;

NEW              RDATA      RDATA
----------- ---------- ----------
2012-11-1            1          5
2012-11-2            3          3
2012-11-5            8

使用道具 举报

回复
论坛徽章:
7
奥运会纪念徽章:手球
日期:2012-09-12 19:30:59迷宫蛋
日期:2013-02-28 09:28:31劳斯莱斯
日期:2013-11-26 15:08:14Jeep
日期:2013-11-27 15:33:432014年世界杯参赛球队: 葡萄牙
日期:2014-05-20 18:26:08优秀写手
日期:2014-08-01 06:00:13暖羊羊
日期:2015-04-17 17:11:45
发表于 2012-11-7 10:00 | 显示全部楼层
将A,B表的查询结果集作连接查询。
select a.col2, a.col1, nvl(b.col1,0)
  from (select col1, col2 from a) t1, (select col1, col2 from b) t2
where t1.col2 = t2.col2(+)

使用道具 举报

回复
认证徽章
论坛徽章:
24
技术图书徽章
日期:2013-08-16 14:31:52问答徽章
日期:2013-11-04 08:53:14目光如炬
日期:2013-12-23 06:00:11目光如炬
日期:2013-12-30 06:00:11明星写手
日期:2014-02-22 06:00:12马上有钱
日期:2014-03-31 14:09:05沸羊羊
日期:2015-05-20 12:42:59秀才
日期:2015-06-24 13:05:36秀才
日期:2015-07-13 09:48:14
发表于 2012-11-7 10:32 | 显示全部楼层
LuiseDalian 发表于 2012-11-7 10:25
oracle 11g下实测

速度啊

使用道具 举报

回复
认证徽章
论坛徽章:
82
2013年新春福章
日期:2013-02-25 14:51:24奥运会纪念徽章:排球
日期:2013-04-11 18:16:37奥运会纪念徽章:曲棍球
日期:2013-04-11 18:16:47奥运会纪念徽章:垒球
日期:2013-04-27 15:03:48奥运会纪念徽章:跳水
日期:2013-04-27 15:04:27奥运会纪念徽章:举重
日期:2013-04-27 15:04:27奥运会纪念徽章:田径
日期:2013-04-27 15:04:27奥运会纪念徽章:赛艇
日期:2013-04-27 15:04:27奥运会纪念徽章:垒球
日期:2013-04-27 15:04:27咸鸭蛋
日期:2013-03-24 21:25:32
发表于 2012-11-7 10:35 | 显示全部楼层
arron刘 发表于 2012-11-7 10:32
速度啊

楼主的帖子,必须速度,呵呵。

使用道具 举报

回复
论坛徽章:
3
ITPUB9周年纪念徽章
日期:2010-10-08 09:28:52ITPUB十周年纪念徽章
日期:2011-11-01 16:20:28ITPUB 11周年纪念徽章
日期:2012-10-10 13:11:14
发表于 2012-11-7 10:37 | 显示全部楼层
楼上很标准的答案呀

使用道具 举报

回复
论坛徽章:
1
ITPUB十周年纪念徽章
日期:2011-11-01 16:26:59
发表于 2012-11-7 10:37 | 显示全部楼层
select nvl(n.new_user,0),o.old_user,o.rdate
  from (select id old_user, rdate from d where d.oon = 'O') o,
       (select id new_user, rdate from d where d.oon = 'N') n
where n.rdate = o.rdate(+)

使用道具 举报

回复
论坛徽章:
1
2013年新春福章
日期:2013-02-25 14:51:24
发表于 2012-11-7 10:48 | 显示全部楼层
本帖最后由 d604060189 于 2012-11-7 10:56 编辑

3楼的那个 USING (MyDate); 是什么意思?,哦,明白了,是连接用的,还可以这么用。挺好

使用道具 举报

回复
认证徽章
论坛徽章:
25
奥运会纪念徽章:射击
日期:2013-01-28 09:12:182014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-03-20 16:13:24马上有房
日期:2014-03-20 16:14:11马上有钱
日期:2014-03-20 16:14:11马上有对象
日期:2014-03-20 16:14:11马上加薪
日期:2014-03-20 16:14:11喜羊羊
日期:2015-04-09 18:46:34秀才
日期:2016-03-24 09:20:52
发表于 2012-11-7 11:30 | 显示全部楼层
  1. CREATE TABLE A
  2. (
  3.     ID NUMBER(4),
  4.     MyDate DATE
  5. );
  6. INSERT INTO A VALUES(1, to_date('2012-11-01', 'YYYY-MM-DD'));
  7. INSERT INTO A VALUES(3, to_date('2012-11-02', 'YYYY-MM-DD'));
  8. INSERT INTO A VALUES(8, to_date('2012-11-05', 'YYYY-MM-DD'));

  9. CREATE TABLE B
  10. (
  11.     ID NUMBER(4),
  12.     MyDate DATE
  13. );

  14. INSERT INTO B VALUES(5, to_date('2012-11-01', 'YYYY-MM-DD'));
  15. INSERT INTO B VALUES(3, to_date('2012-11-02', 'YYYY-MM-DD'));


  16. SELECT MyDate AS 日期, nvl(A.ID, 0) AS 新用户, nvl(B.ID, 0) AS 老用户
  17. FROM A FULL OUTER JOIN B
  18. USING (MyDate);
复制代码
这个的确很不错啊。很简单的问题。版主怎么哪里讨论啊。

使用道具 举报

回复

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

本版积分规则 发表回复

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