Excluding some combinations from left join in MySQL

一世执手 提交于 2020-01-07 01:58:58

问题


I'm analyzing game data. My data includes game id (GID), player id (PID), and Time slice (T),.... Table A and B are two tables that created by my queries as follow:

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

I need to find in which commands and orders are done in each time slice (also their counts). The result should be as follows:

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

In general in T=t we could have 0 to n commands or orders. I need the union of all commands and orders for T=t.


回答1:


Schema

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);

Note that with the use of unions, the first query in a union drives what the column names are targeted as for the final output:

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

So the 2nd and thereafter queries in a union can be sloppy about it if they want, at least insofar as their alleged column names.

The first query below, though it generates the same output at least shown to you here via the command line utility output, delivers slightly different results than the second query if I run it thru 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 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)

The second version below takes the minor additional effort to use a rownum to hit your result ordering if that was even important inside of the GID,PID,T blocks. The second result set shows the same ordering for me at least via the mysql command line tool and 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)

In either case, the theOrder column was used to force the output of NULL to be at the bottom of each GID,PID,T block.

I present them as a way for you to visualize the use of variables and ordering to hit your desired output ordering as you make changes.




回答2:


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


来源:https://stackoverflow.com/questions/37751091/excluding-some-combinations-from-left-join-in-mysql

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!