从MySQL中的左连接中排除一些组合

时间:2016-06-10 14:43:51

标签: mysql outer-join

我正在分析游戏数据。我的数据包括游戏ID(GID),玩家ID(PID)和时间片(T),....表A和B是我的查询创建的两个表,如下所示:

Table A
GID, PID, T, command_freq, command_id
1,   1,   0, 17, 10
1,   1,   0, 4, 5
1,   1,   1, 26, 10
1,   1,   1, 6, 5
1,   1,   2, 5, 5
1,   1,   2, 3, 10
1,   1,   5, 7, 10

Table B
GID, PID, T, order_freq, order_id
 1,  1,   0, 7, 40
 1,  1,   2, 3, 40
 1,  1,   2, 11, 42
 1,  1,   5, 1, 40

我需要找到每个时间片中的命令和命令(也是它们的计数)。结果应如下:

GID, PID, T, command_count, command_id, order_count, order_id
1,   1,   0,  17,           10,            Null, Null
1,   1,   0,  4,            5 ,            Null, Null
1,   1,   0,  Null,         Null,          7, 40
1,   1,   1,  26,           10,            Null, Null
1,   1,   1,  6,            5,             Null, Null
1,   1,   2,  5,            5,             Null, Null
1,   1,   2,  3,            10,            Null, Null
1,   1,   2,  Null,         Null,          3, 40
1,   1,   2,  Null,         Null,          11, 42
1,   1,   5,  7,            10,            Null, Null
1,   1,   5,  Null,         Null,          1, 40

一般来说,在T = t时,我们可以有0到n个命令或命令。我需要T = t的所有命令和命令的并集。

2 个答案:

答案 0 :(得分:1)

模式

drop table if exists ta;
create table ta (GID int,PID int,T int,command_freq int, command_id int);
insert into ta values
(1,   1,   0, 17, 10),
(1,   1,   0, 4, 5),
(1,   1,   1, 26, 10),
(1,   1,   1, 6, 5),
(1,   1,   2, 5, 5),
(1,   1,   2, 3, 10),
(1,   1,   5, 7, 10);

drop table if exists tb;
create table tb (gid int,pid int,t int,order_freq int,order_id int);
insert into tb values
( 1,  1,   0, 7, 40),
( 1,  1,   2, 3, 40),
( 1,  1,   2, 11, 42),
( 1,  1,   5, 1, 40);

请注意,使用联合,联合中的第一个查询会驱动列名作为最终输出的目标:

GID, PID, T, command_count, command_id, order_count, order_id

因此,如果他们想要的话,联盟中的第二个及以后的查询可能会很草率,至少就他们所谓的列名而言。

下面的第一个查询,虽然它通过命令行实用程序输出生成至少向您显示的相同输出此处,但是提供的结果与第二个查询略有不同我通过My​​SQL Workbench运行它。

select GID,PID,T,command_count,command_id,order_count,order_id 
from 
(   select GID, PID, T, command_freq as command_count, command_id, null as order_count, null as order_id, 1 as theOrder from ta 
    union  
    select GID, PID, T, null as command_count, null, order_freq as order_count, order_id, 2 as theOrder from tb 
) xDerived 
order by GID,PID,T,theOrder; 
+------+------+------+---------------+------------+-------------+----------+
| GID  | PID  | T    | command_count | command_id | order_count | order_id |
+------+------+------+---------------+------------+-------------+----------+
|    1 |    1 |    0 |            17 |         10 |        NULL |     NULL |
|    1 |    1 |    0 |             4 |          5 |        NULL |     NULL |
|    1 |    1 |    0 |          NULL |       NULL |           7 |       40 |
|    1 |    1 |    1 |            26 |         10 |        NULL |     NULL |
|    1 |    1 |    1 |             6 |          5 |        NULL |     NULL |
|    1 |    1 |    2 |             5 |          5 |        NULL |     NULL |
|    1 |    1 |    2 |             3 |         10 |        NULL |     NULL |
|    1 |    1 |    2 |          NULL |       NULL |          11 |       42 |
|    1 |    1 |    2 |          NULL |       NULL |           3 |       40 |
|    1 |    1 |    5 |             7 |         10 |        NULL |     NULL |
|    1 |    1 |    5 |          NULL |       NULL |           1 |       40 |
+------+------+------+---------------+------------+-------------+----------+
11 rows in set (0.00 sec)

如果在GID,PID,T块内部甚至是重要的话,下面的第二个版本会花费额外的精力来使用rownum命中结果排序。第二个结果集至少通过mysql命令行工具和MySQL Workbench显示了相同的顺序:

select GID,PID,T,command_count,command_id,order_count,order_id 
from 
(   select GID, PID, T, command_freq as command_count, command_id, null as order_count, null as order_id, 1 as theOrder,@rn1:=@rn1+1 as rownum 
    from ta 
    cross join (select @rn1:=0) xParams1 
    union  
    select GID, PID, T, null as command_count, null, order_freq as order_count, order_id, 2 as theOrder,@rn2:=@rn2+1 as rownum   from tb 
    cross join (select @rn2:=0) xParams2 
) xDerived 
order by GID,PID,T,theOrder,rownum; 
+------+------+------+---------------+------------+-------------+----------+
| GID  | PID  | T    | command_count | command_id | order_count | order_id |
+------+------+------+---------------+------------+-------------+----------+
|    1 |    1 |    0 |            17 |         10 |        NULL |     NULL |
|    1 |    1 |    0 |             4 |          5 |        NULL |     NULL |
|    1 |    1 |    0 |          NULL |       NULL |           7 |       40 |
|    1 |    1 |    1 |            26 |         10 |        NULL |     NULL |
|    1 |    1 |    1 |             6 |          5 |        NULL |     NULL |
|    1 |    1 |    2 |             5 |          5 |        NULL |     NULL |
|    1 |    1 |    2 |             3 |         10 |        NULL |     NULL |
|    1 |    1 |    2 |          NULL |       NULL |           3 |       40 |
|    1 |    1 |    2 |          NULL |       NULL |          11 |       42 |
|    1 |    1 |    5 |             7 |         10 |        NULL |     NULL |
|    1 |    1 |    5 |          NULL |       NULL |           1 |       40 |
+------+------+------+---------------+------------+-------------+----------+
11 rows in set (0.00 sec)

在任何一种情况下,theOrder列都用于强制NULL的输出位于每个GID,PID,T块的底部。

我将它们作为一种方式让您可视化变量的使用,并在您进行更改时按顺序点击所需的输出顺序。

答案 1 :(得分:0)

declare @A table (gid int,pid int,t int,f1 int, f2 int)
insert into @a values
(1,   1,   0, 17, 10),
(1,   1,   0, 4, 5),
(1,   1,   1, 26, 10),
(1,   1,   1, 6, 5),
(1,   1,   2, 5, 5),
(1,   1,   2, 3, 10),
(1,   1,   5, 7, 10),
(1,   1,   6, 3, 7),
(1,   1,   6, 8, 5)

declare @b table (gid int,pid int,t int,f3 int,f4 int)
insert into @b
values
( 1,  1,   0, 7, 40),
( 1,  1,   2, 3, 40),
( 1,  1,   5, 1, 40)


select  a.gid,a.pid,a.t,a.f1,a.f2,b.f3,b.f4 
from    @a a
join    @b b on b.gid = a.gid and b.pid = a.pid and b.t = a.t
where   a.t <> 0
union
select  a.gid,a.pid,a.t,a.f1,a.f2,null,null
from    @a a
where   a.t = 0
union
select  b.gid,b.pid,b.t,null,null,b.f3,b.f4
from    @b b
where   b.t = 0