MySQL 匹配同一表中的列

标签 mysql sql database-design

好的,一点入门知识;我是一名专业的 PHP/JS/C 开发人员,但从未完全掌握 MySQL。如果您能回答我的问题,那就太好了,但如果您能为我指明好的资源的方向,以了解复杂的 MySQL 查询该做什么和不该做什么(主要是从效率的角度来看),那也同样有帮助)。

目标

我需要在单个表中查找相似性/重叠,同时仍然提取整个结果集(与另一个表中的实际标题/描述内容进行 LEFT JOIN)。

表格极其简单;它包含 3 列(页面用户时间)。

基本上每个查询都会有两个用户。我需要提取与 User 1 匹配的所有结果的计数、与 User 2 匹配的所有结果的计数,以及重叠的所有列(加上 LEFT JOIN)(其中 用户 1用户 2 在表中有匹配项。

示例查询

这个查询可以工作,但是它非常慢(需要几分钟才能运行)并且我猜测由于子查询而效率低下。如果任何 SQL 专家能够指出一种更有效的方法来做到这一点(以及原因),我们将不胜感激。

SELECT DISTINCT `page`, 
    (SELECT COUNT(*) FROM `m_likes` WHERE `user` = "1") AS userLikes,
    (SELECT COUNT(*) FROM `m_likes` WHERE `user` = "2") AS friendLikes

    FROM `m_likes` LEFT JOIN `app_pages` AS page ON (page.id = `page`)

        WHERE `page` IN (SELECT `page` FROM `m_likes` WHERE `user` = "1") 
        AND `page` IN (SELECT `page` FROM `m_likes` WHERE `user` = "2")

        AND (`user` = "1" OR `user` = "2")

解释查询结果

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY     m_likes index   NULL    page    604 NULL    35043   Using where; Using index; Using temporary
1   PRIMARY     page    eq_ref  PRIMARY PRIMARY 767 tablename.m_likes.page  1   
5   DEPENDENT SUBQUERY  m_likes unique_subquery page    page    604 func,const      1   Using index; Using where
4   DEPENDENT SUBQUERY  m_likes unique_subquery page    page    604 func,const      1   Using index; Using where
3   SUBQUERY    m_likes index   NULL    page    604 NULL    35043   Using where; Using index
2   SUBQUERY    m_likes index   NULL    page    604 NULL    35043   Using where; Using index

表架构

app_pages:id VARCHAR(255)、名称 VARCHAR(255)、类别 VARCHAR(255)

m_likes:页面 VARCHAR(255)、用户 VARCHAR(255)、时间 INT(20)

m_likes.page = app_pages.id

还值得注意的是,不幸的是,用户和页面 ID 必须是 VARCHAR 而不是 INT,因为不能保证在 64 位系统上运行,并且某些 ID 值大于 64 位系统上允许的最大值。 32 位系统...希望这不会对性能造成重大影响。

输出示例

array (size=156)
  0 => 
    array (size=6)
      'page' => string '100861973286778' (length=15)
      'time' => string '1297383617' (length=10)
      'name' => string 'Leila' (length=5)
      'category' => string 'Book' (length=4)
      'userLikes' => string '104' (length=3)
      'friendLikes' => string '52' (length=2)
  1 => 
    array (size=6)
      'page' => string '10150160788195604' (length=17)
      'time' => string '1272653871' (length=10)
      'name' => string 'Frisbee Golfing' (length=15)
      'category' => string 'Interest' (length=8)
      'userLikes' => string '104' (length=3)
      'friendLikes' => string '52' (length=2)

最佳答案

您的查询运行如此缓慢的原因是您正在执行四个个单独的子查询,这些子查询实际上最终针对EACH行执行。

相反,您可以对子选择进行笛卡尔积来获取计数(仅执行一次):

SELECT a.page, c.userLikes, c.friendLikes
FROM m_likes a
INNER JOIN app_pages b ON a.page = b.id
CROSS JOIN
(
    SELECT
        COUNT(CASE WHEN user = '1' THEN 1 END) AS userLikes,
        COUNT(CASE WHEN user = '2' THEN 1 END) AS friendLikes
    FROM m_likes
    WHERE user IN ('1','2')
) c
WHERE a.user IN ('1','2')
GROUP BY a.page
HAVING COUNT(1) = 2

此查询将检索用户 1 和 2 都喜欢的所有页面,以及他们喜欢的总计数(将在结果集中重复)。

关于MySQL 匹配同一表中的列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11604800/

相关文章:

c# - 连接到网络上的 MySQL 数据库

java - 我正在使用 JNDI 连接到 mysql 数据库,但在执行时最终会抛出异常

sql - 将查询中的单个列与多个列聚合

MySQL 组合表并将具有唯一行 ID 的多个列转置为非唯一行

c# - 数据库双连接关系插入问题

使用外键关系的 MySQL 查询

php - 防止 PHP 打印空数组结果?

mysql - SQLite - 如何将 Money 转换为 Int 然后插入到表中

mysql - 将 SQL "Concat"转换为 Activerecord

sql - 实现基于策略、基于时间和基于客户的定价