【问题标题】:Combining multiple queries with 4 joins?将多个查询与 4 个连接结合起来?
【发布时间】:2020-11-04 11:56:25
【问题描述】:

我在ti_userevent 数据库中运行了一个查询,该查询结合了用户在多个游戏会话中的游戏会话长度,而是返回了每个玩家在设定时间和日期之间的总游戏长度(而不是玩家 1 的 4 个会话,它返回 1 并给出所有 4 个会话的总播放时长)。

此查询允许我为我在 MetaBase 中查找的数据设置日期和时间范围,并在提供的时间范围内返回每个用户在多个会话中的玩家 ID、玩家姓名和总游戏时长。

这是查询。

SELECT t2.playername,
    (EXTRACT(EPOCH
        FROM ( MAX(t.local_time) - MIN(t.local_time)) ::INTERVAL)/60)::integer as duration
            FROM ti_userevent t
        JOIN
    (SELECT DISTINCT t2.value as playerName, t2.session_id
            FROM ti_userevent t2
                WHERE context = 'Player' 
                AND
                action = 'Name'
                    [[AND local_time >= {{StartTime}}::timestamp at time zone 'US/Pacific']]
                    [[AND local_time < {{EndTime}}::timestamp at time zone 'US/Pacific']]
            ) t2
        ON t2.session_id = t.session_id
GROUP BY t2.playername;

示例数据:

   User ID        User Name   Play Length of all sessions
    ID1             Name 1          105
    ID2             Name 2          215
    ID3             Name 3          352

但是,我还想从查询中获得他们的平均 FPS、GPU 和帧性能。问题是,这些都存储在同一张表中!

为了获得平均 GPU 性能,我运行了以下命令,这只给出了基于内部版本号的平均性能。

SELECT
    session_id
    , value::decimal as AvgGpuMs
FROM 
    ti_userevent
WHERE 
        context = 'Perf'
    AND action = 'GpuMs'
    AND session_id IN 
        (SELECT DISTINCT session_id
            FROM 
                ti_userevent
            WHERE 
                action = 'BuildNum'
                and value = {{BuildNum}})

示例数据:

user_id    session_id    avggpums
ID1         session1       8.2
ID2         session1       8.7
ID3         session1       9.7

我必须针对 AvgFPS 和 AvgFrameMs 性能运行上述相同的查询。

我想要将 3 个 AvgFPS、AvgFrameMs 和 AvgGPUms 查询组合到第一个 Play 会话长度查询中。我想让它们在第一个查询中都超出时间范围...我已经尝试了几次,但很难让它返回我所追求的数据。

我在 SQL 方面不是最好的,所以我希望这里有人可以帮助我。感谢您的所有帮助!

【问题讨论】:

  • 你能指定你使用的是哪个数据库吗?
  • 嗨 Drum,数据库是 ti_userevent。我将把它添加到问题中,很抱歉造成混淆并感谢您的帮助。
  • 我的意思是你在使用 Postgres、MySQL、SQLite 等吗?
  • 我认为这是一个奇怪的问题,因为它就在 FROM 语句中...... Postgres,抱歉造成混淆,我会将它添加到标签中。
  • 您能否调整第一个查询,因为它的列与示例数据不匹配?此外,您是否需要按玩家和会话级别分组的期望结果?最后,其他平均值是否遵循与上下文和内部版本号的 GPU 性能相同的逻辑,但操作不同?

标签: sql postgresql


【解决方案1】:

考虑在会话级别进行条件计算,然后在玩家级别进行平均。此外,使用 CTE 来提高底层资源之间的可读性。

注意:在定义 FPSFrame 时进行了假设,可能需要调整。

WITH session_time AS (
    SELECT DISTINCT value as playerName
           , session_id
    FROM ti_userevent
    WHERE context = 'Player' 
      AND action = 'Name'
      [[AND local_time >= {{StartTime}}::timestamp at time zone 'US/Pacific']]
      [[AND local_time < {{EndTime}}::timestamp at time zone 'US/Pacific']]
), session_metrics AS (
    SELECT session_id
          , AVG((CASE WHEN context='Perf' AND action='GpuMs' THEN value END)::decimal) AS GpuMs
          , AVG((CASE WHEN context='Perf' AND action='FPS'   THEN value END)::decimal) AS FPS
          , AVG((CASE WHEN context='Perf' AND action='Frame' THEN value END)::decimal) AS Frame
    FROM ti_userevent
    WHERE session_id IN 
       (SELECT session_id
        FROM ti_userevent
        WHERE action = 'BuildNum'
          AND value = {{BuildNum}})
    GROUP BY session_id
)

SELECT t.playername
       , (EXTRACT(EPOCH FROM (MAX(ue.local_time) - MIN(ue.local_time))::INTERVAL)/60)::integer AS duration
       , AVG(m.GpuMs) AS AvgGpuMs
       , AVG(m.FPS)   AS AvgFPS
       , AVG(m.Frame) AS AvgFrame
 
FROM ti_userevent ue
INNER JOIN session_time t 
   ON ue.session_id = t.session_id
INNER JOIN session_metrics m
   ON ue.session_id = m.session_id
GROUP BY t.playername;

顺便说一句,您的表似乎是 entity-attribute value model(即关键字-值对中的行)。虽然有很多讨论是否这是一个最佳设计,但如上所示,关系、规范化模型中的大多数简单查询在 EAV 模型中将变得更加复杂。在关系框架中,您将有两个用于一对多关系的用户和会话表。

【讨论】:

  • 你太棒了,非常感谢 Parfait!我也同意 EAV 模型,它比必要的复杂得多。
猜你喜欢
  • 2013-11-27
  • 2021-09-28
  • 1970-01-01
  • 2015-07-16
  • 2017-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
相关资源
最近更新 更多