我有以下问题:我有三个表:日志(log)、媒体和用户.

CREATE TABLE `users` (
  `id` INTEGER NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB
ROW_FORMAT=DEFAULT;
CREATE TABLE `media` (
  `id` INTEGER NOT NULL AUTO_INCREMENT,
  `title` VARCHAR(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB
ROW_FORMAT=DEFAULT;
CREATE TABLE `log` (
  `id` INTEGER NOT NULL AUTO_INCREMENT,
  `action` VARCHAR(20) NOT NULL,
  `action_time` DATETIME NOT NULL,
  `user_id` INTEGER NOT NULL,
  `affected_user_id` INTEGER DEFAULT NULL,
  `media_id` INTEGER DEFAULT NULL,
  `comment` TEXT DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB
ROW_FORMAT=DEFAULT;

The point with the log table is, that every action that is made, is done by a user, but some actions affect a user, and some actions affect a media, but not always. Some actions affect both a user and a media. The columns user_id, affected_user_id are foreign keys to users.id
The column media_id is a foreign key to media.id If there isn't a value for the column, the value is NULL.

我想要做的是对LOG进行SELECT查询,并与其他两个表进行内部联接.

首先,我try 了这个查询,但不知道有什么问题,所以这将是我第一次try 这样做:

SELECT log.action, log.action_time, log.user_id, user_name_table.name AS user_name, 
log.affected_user_id, affected_user_name_table.name AS affected_user_name, 
log.media_id, media.title AS media_title, log.comment 
FROM log 
INNER JOIN users AS user_name_table ON user_name_table.id = log.user_id 
INNER JOIN users AS affected_user_name_table ON affected_user_name_table.id = log.affected_user_id 
INNER JOIN media ON media.id = log.media_id 
WHERE log.user_id=1 OR log.affected_user_id=1

我在网上查找了如何在两列上内部连接同一张表,我真的不知道它是否正确,也许这也是问题所在.我原以为这个查询会返回日志(log)表的所有列,以及与user_id和Affated_user_id关联的用户的名称.

在日志(log)表中,有足够的行具有USER_ID=1或IMPACTED_USER_ID=1.但是不知何故,我的结果集是空的.我没有收到错误消息,所以我的查询语法应该是正确的.

我还try 了其他几个类似的版本:

SELECT log.action, log.action_time, log.user_id, users.name AS user_name, log.affected_user_id, 
log.media_id, media.title AS media_title, log.comment 
FROM log 
INNER JOIN users ON users.id = log.user_id OR users.id=log.affected_user_id
INNER JOIN media ON media.id = log.media_id 
WHERE log.user_id=1 OR log.affected_user_id=1
SELECT log.action, log.action_time, log.user_id, users.name AS user_name, 
log.affected_user_id, 
log.media_id, media.title AS media_title, log.comment 
FROM log 
INNER JOIN users ON users.id = log.user_id = affected_user_id
INNER JOIN media ON media.id = log.media_id 
WHERE log.user_id=1 OR log.affected_user_id=1

我在网上搜索了解决方案,但似乎没有找到.我甚至询问了ChatGPT:),但它说我的查询完全正确,应该返回我的结果集.

推荐答案

如果我理解正确的话,这会有帮助吗?

SELECT log.action,
       log.action_time,
       log.user_id,
       users.name AS user_name,
       log.affected_user_id,
       log.media_id,
       media.title AS media_title,
       log.comment
  FROM log
       INNER JOIN users
          ON    (    users.id = log.user_id
                 AND log.user_id = 1)
             OR (    users.id = log.affected_user_id
                 AND log.affected_user_id = 1)
       INNER JOIN media ON media.id = log.media_id

[EDIT],在您发布示例数据后:

SQL> SELECT * FROM users;

        ID NAME
---------- -----
         1 Alex
         2 Heinz
         3 Frank

SQL> SELECT * FROM media;

        ID TITLE
---------- ---------------
         1 Harry Potter
         2 Some other book
         3 No idea

SQL> SELECT * FROM log;

        ID ACTION       ACTION_TIME            USER_ID AFFECTED_USER_ID   MEDIA_ID
---------- ------------ ------------------- ---------- ---------------- ----------
         1 MEDIA_EDIT   2023-08-23 17:56:04          1                           5
         2 USER_EDIT    2023-08-23 17:56:04          1                3
         3 MEDIA_BORROW 2023-08-23 17:56:04          1                3          1

log表连接到userstwice的查询:一次用于log.user_id(内连接),另一次用于log.affected_user_id(外连接).

SQL> SELECT l.action,
  2         l.action_time,
  3         u.name AS user_name,
  4         au.name AS affected_user_name,
  5         m.title media_title
  6    FROM LOG  l
  7         JOIN users u ON u.id = l.user_id
  8         LEFT JOIN users au ON au.id = l.affected_user_id
  9         LEFT JOIN media m ON m.id = l.media_id;

ACTION       ACTION_TIME         USER_NAME AFFECTED_USER_NAME      MEDIA_TITLE
------------ ------------------- --------- ----------------------- ---------------
MEDIA_BORROW 2023-08-23 17:56:04 Alex      Frank                   Harry Potter
USER_EDIT    2023-08-23 17:56:04 Alex      Frank
MEDIA_EDIT   2023-08-23 17:56:04 Alex

SQL>

Mysql相关问答推荐

MariaDB字段+1

客户跨订阅的跨时间线计数

为什么我安装MySQL时不能使用3306端口?

左联接重复问题

MySQL连接序列

数组上的MySQL、JSON_CONTAINS用法

如何从MySQL数据库中提取入职第一个月的工作天数?

我是否需要在 N+1 列上建立索引,才能有效地在 N 列上执行 SELECT,并按其他列排序?

在 MYSQL 8 中的 JSON 字段上的 SELECT 中返回所有键及其数组项

MySQL函数 - 如何对select查询应用多个条件

为什么order by子句可以利用索引?

将 Go var 传递给 MySQL - try 在 Go lang 程序 (MySQL db) 中执行 db.Exec 时出错

MySql,如何从列中替换某种格式的字符串

如何在 SQL 的计算列中显示小数点后两位?

这是将表单数据插入 MySQL 数据库的安全方法吗?

MySQL触发器在某些条件下防止INSERT

外键可以引用非唯一索引吗?

如何将 MySQL 查询结果存储在另一个表中?

将mysql查询输出存储到shell变量中

获得上个月的第一天和最后一天的最佳方式?