最后x个类型事件的SQL

时间:2013-12-23 23:02:28

标签: mysql sql

我试图找出哪些成员在事件类型重要的最后x事件中出席率最高

此处的示例结构

http://sqlfiddle.com/#!2/bde53/1

attended_id是会员ID,鉴于许多事件类型的事件,如果可能的话我想要这样的事情

 attended_id | last 6 event 1 | last 12 event 2 |  2013 event 3 |
       1             6               10                6
       2             5                9                12
       3             2                8                7

2013 event 3表示2013年发生的所有活动ID 3 这是可能的,还是最好导出到excel以获取此信息?

如果使这个查询更容易,也可以使用新结构。数字应该很容易改变,例如最后8个事件1而不是最后6个事件

我为每个人都有SQL,但不能将它们组合起来

去年成员身份

的事件
SELECT attended_id, year(x.date), count(event_id)  FROM events e INNER JOIN events_types x USING (event_id)
INNER JOIN events_type t USING (event_type)
WHERE t.event_type = 1
group by attended_id, year(x.`date`);

最后x个类型

的事件
SELECT attended_id, count(event_id) FROM events e INNER JOIN events_types x USING (event_id)
INNER JOIN events_type t USING (event_type)
WHERE t.event_type = 1 and
e.event_id >= (             
select event_id from events_types where event_type = 1 order by event_id desc
limit 1,1              
)
group by attended_id

我不能将这些组合在同一个查询中显示

2 个答案:

答案 0 :(得分:3)

查询可以通过以下方式实现:

  • 使用user defined variables一次性计算每种事件类型的年龄排名
  • 将出勤记录加入排名结果,并在attended_id
  • 上进行分组

以下是查询:

select
  a.attended_id,
  sum(event_type = 1 and rank <= 6) `last 6 event 1`,
  sum(event_type = 2 and rank <= 12) `last 12 event 2`,
  sum(event_type = 3 and year(date) = 2013) `2013 event 3`
from events a
left join (
  select event_id, event_type, date,
    (@row := if(@prev is null or @row is null or @prev != event_type, 1, @row + 1)) rank,
    (@prev := event_type) prev
  from (select event_id, event_type, date
    from events_types
    order by event_type, date desc) e) r on r.event_id = a.event_id
group by 1

这是SQLFiddle

正如您所看到的,将变量更改为具有不同的事件类型和“最后n”值,甚至为不同的细分添加更多列,这是一件简单的事情。

注意:

  • 最内层查询按事件排序行,然后按日期最新到最新排序。这是排名逻辑正常工作所必需的
  • 变量为null的测试只需要第一行,但用于避免必须在单独的语句中定义变量,使查询成为一个独立的查询,这通常是必需,因为大多数数据库库不支持在单个调用中执行的多个查询
  • 通过求和条件可以避免
  • 冗长的case语句;在mysql中,布尔值是1表示真,0表示假,所以总结条件计算它是多少次真实

最后一点,您的表名有点令人困惑。可以对它们进行更改以使其更清楚地表达它们的含义。我建议这些改变:

  • events - &gt; attendances
  • events_types - &gt; events
  • events_type - &gt; event_types

答案 1 :(得分:2)

请尝试此sqlFiddle

SELECT T1.attended_id,
       T2.`last 6 event 1`,
       T3.`last 12 event 2`,
       T4.`2013 event 3`
FROM
    (SELECT DISTINCT attended_id
     FROM events)T1
LEFT JOIN
    (SELECT e.attended_id,COUNT(*) as `last 6 event 1`
     FROM events e
     INNER JOIN (SELECT event_id,event_type,date
                 FROM events_types
                 WHERE event_type = 1
                 ORDER BY date DESC
                 LIMIT 6
                ) et
     USING (event_id)
     GROUP BY e.attended_id
     )T2
ON (T1.attended_id = T2.attended_id)
LEFT JOIN
    (SELECT e.attended_id,COUNT(*) as `last 12 event 2`
     FROM events e
     INNER JOIN (SELECT event_id,event_type,date
                 FROM events_types
                 WHERE event_type = 2
                 ORDER BY date DESC
                 LIMIT 12
                ) et
     USING (event_id)
     GROUP BY e.attended_id
     )T3
ON (T1.attended_id = T3.attended_id)
LEFT JOIN
    (SELECT e.attended_id,COUNT(*) as `2013 event 3`
     FROM events e
     INNER JOIN (SELECT event_id,event_type,date
                 FROM events_types
                 WHERE event_type = 3
                 AND year(date) = 2013
                 ) et
     USING (event_id)
     GROUP BY e.attended_id
     )T4
ON (T1.attended_id = T4.attended_id)

你的sqlFiddle没有足够的数据,所以我添加了一些随机events和一些event_types,我注意到你不需要加入event_type你没有从event_type抓取任何信息,但只是想要一个计数。

如果您想要最后8个活动1,只需将LIMIT 6更改为LIMIT 8 et内的T2

或者您可以使用以下代码

尝试此sqlFiddle
SELECT e.attended_id,
       SUM(IF(event_type = 1 AND typeRank BETWEEN 1 AND 6,1,0)) as `last 6 event 1`,
       SUM(IF(event_type = 2 AND typeRank BETWEEN 1 AND 12,1,0)) as `last 12 event 2`,
       SUM(IF(event_type = 3 AND YEAR(date) = 2013,1,0)) as `2013 event 3`
FROM events e
INNER JOIN (SELECT event_id,event_type,date,
                   IF (@prevType != event_type,@typeRank:=1,@typeRank:=@typeRank+1) as typeRank,
                   @prevType := event_type
            FROM events_types,(SELECT @prevType:=0,@typeRank:=0)R
            ORDER BY event_type,date DESC
            ) et
USING (event_id)
GROUP BY e.attended_id

如果您想要最后8个活动1,只需将BETWEEN 1 AND 6更改为BETWEEN 1 AND 8

即可