问题
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