超级复杂的mysql查询

时间:2016-11-03 17:54:32

标签: mysql database select join

我查询的数据库(Mysql)来自电话系统,我需要读取有多少代理(event_parties.agent_id)被记录到不同的组(event_groups.group_id)。

每次代理登录到某个组时,如果注销 event_id = 30 event_id = 29 事件表中输入新记录>同时,表 event_parties 中的新条目与 g_event_id 相同,agent_id代表代理,  同样在表 events_groups 中,新条目显示为具有相同的 g_event_id ,group_id表示代理登入/注销的组合(在表event_groups内,相同的g_event_id可能相同)如果代理同时登录/注销多个组,则可以有多个条目。

所以我的想法是我可以通过选择所有没有较新条目(event_time)且具有相同event_groups.group_id和相同event_parties.agent_id并且events.event_id介于29和之间的记录来获取登录代理和group_id。 30.

events.event_id = 29表示代理登录。
events.event_id = 30表示代理注销。

设计这样一个mysql选择时遇到了一些严重困难:(

以下是每个表格中的一些示例数据。

表:
事件

g_event_id   event_id   event_time
----------   --------   ----------
7816         31     2016-11-03 09:46:18
7815         30     2016-11-03 09:45:18
7814         31     2016-11-03 09:44:18
7813         29     2016-11-03 09:43:18 
7812         30     2016-11-03 09:42:18
7811         29     2016-11-03 09:41:18
7810         31     2016-11-03 09:40:18 
7809         29     2016-11-03 09:39:18
7808         31     2016-11-03 09:38:18
7807         7      2016-11-03 09:37:18
7806         29     2016-11-03 09:36:18
7805         30     2016-11-03 09:35:18
7804         30     2016-11-03 09:34:18
7803         29     2016-11-03 09:33:18
7802         29     2016-11-03 09:32:18

表: 的 event_parties

g_event_id   agent_id
----------   --------
7816            1
7815            1
7814            1
7813            1
7812            1
7811            1
7810            2
7809            2
7808            2
7807            3
7806            3
7805            3
7804            3
7803            3
7802            3

表: event_groups

g_event_id   group_id
----------   --------
7816            1
7815            1
7814            1
7813            1
7813            2
7813            3
7813            4
7812            1
7811            1
7810            1
7809            1
7808            1
7807            1
7806            1
7806            3
7805            4
7804            1
7804            2
7803            4
7802            1
7802            2

从上表中我希望我的select语句结果为:

group_id    agent_id
--------    --------
4           1
3           1
2           1
1           2
1           3
3           3

这样的查询是否可行,是否有任何sql天才:)

/克里斯蒂安

2 个答案:

答案 0 :(得分:2)

SELECT group_id, agent_id
FROM (SELECT agent_id, eg.group_id, if(event_id = 29, 1, -1) AS transitions
      FROM event_parties      ep
           JOIN `events` e ON ep.g_event_id = e.g_event_id
           JOIN event_groups eg ON ep.g_event_id = eg.g_event_id
      WHERE e.event_id IN (29, 30)) AS t
GROUP BY agent_id, group_id
HAVING sum(transitions) > 0
ORDER BY agent_id, group_id DESC

Link to SQL Fiddle

我认为这会做你所说的。对于每个代理/组合,如果它们登录,则将转换数设置为1,如果它们注销,则设置为-1。查看整个数据集,如果他们已登录然后注销,则特定代理组的总和将为0,这将在外部查询中计算。

这取决于不从特定代理/组合的注销事件开始。如果您正在查看的数据集以注​​销事件开始,则用户将永远不会被注销。

或者,你可以通过查看最后一条记录得出相同的结果,并确定它是29还是30,并且只显示那些29。

SELECT group_id, agent_id
FROM (SELECT agent_id, group_id, max(e.g_event_id) AS last_event_id
      FROM event_parties      ep
           JOIN `events` e ON ep.g_event_id = e.g_event_id
           JOIN event_groups eg ON ep.g_event_id = eg.g_event_id
      WHERE e.event_id IN (29, 30)
      GROUP BY agent_id, group_id) AS last_event
     JOIN `events` e ON e.g_event_id = last_event.last_event_id
WHERE e.event_id = 29;

这更少依赖于你在系列中的开始位置,但是连接稍微复杂一些。

Link to SQL Fiddle

使用natural join更改FWIW语法样式:

select group_id, agent_id 
  from ( select agent_id, group_id, 
                max( g_event_id ) as g_event_id 
           from event_parties natural join `events` natural join event_groups
          where event_id in (29, 30)
          group
             by agent_id, group_id ) as last_event
       natural join `events`
 where event_id = 29;

答案 1 :(得分:0)

我现在做一个演示,然后告诉我你想要什么

select g.group_id,p.agent_id from event_groups g 
join event_parties p on g.g_event_id=p.g_event_id
join events e on p.g_event_id =e.g_event_id where e.event_id=29