【问题标题】:What is an efficient way to compute cross tab in MySQL?在 MySQL 中计算交叉表的有效方法是什么?
【发布时间】:2015-03-07 07:10:45
【问题描述】:

我有一个名为 messages 的表,其中包含两列:userA 和 userB。

每个用户都有一个类型:typeA 或 typeB。

我想计算不同类型用户之间发送的消息数量的交叉表。用户也可以是 typeA 和 typeB。类型存储在不同的表中:(id:1, typeA), (id:2, typeB)

userA/userB | typeA | typeB
-----
typeA          2000    81348
-----
typeB         18348    12938

如何有效地做到这一点?假设我有 100000 条消息。如果我为 userA 执行第一个内部连接:在最坏的情况下,我会得到 7*100000 条记录。现在,如果我为 userB 执行第二个内部联接:我将获得 7*7*100000 条记录。第二个连接查询需要很长时间。

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: mysql join optimization


    【解决方案1】:
    SELECT src.type AS `UserA/UserB`, SUM(dest.type = 'typeA') AS typeA, SUM(dest.type = 'typeB') AS typeB
    FROM messages AS msgsrc
    JOIN users AS src ON msgsrc.userA = src.id
    JOIN messages AS msgdest ON msgsrc.userA = msgdest.userB
    JOIN users AS dest ON msgdest.userB = dest.id
    GROUP BY `UserA/UserB`
    

    如果用户类型更多,继续添加更多SUM(dest.type = 'TypeX')列。

    如果您不需要单独列中的总和,您可以这样做:

    SELECT src.type AS srcType, dest.type AS destType, COUNT(*) AS count
    FROM messages AS msgsrc
    JOIN users AS src ON msgsrc.userA = src.id
    JOIN messages AS msgdest ON msgsrc.userA = msgdest.userB
    JOIN users AS dest ON msgdest.userB = dest.id
    GROUP BY srcType, destType
    

    这不需要修改来处理更多类型,并且可能更有效,因为它不必生成那么大的中间表。

    【讨论】:

    • 我应该注意到类型存储在不同的表中(刚刚编辑过的操作)。
    • 我添加了与 users 表的连接,以将用户 ID 映射到类型。
    • 我会试试这个,但它并没有解决我的主要问题。将这些表连接在一起将产生数百万行。
    • 确保你有索引,这是你能做的最好的。
    猜你喜欢
    • 2011-07-13
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 2014-08-16
    相关资源
    最近更新 更多