【问题标题】:MySQL Loading Rows via String's ContentsMySQL将行加载到字符串内容
【发布时间】:2019-02-19 20:36:12
【问题描述】:

我正在为我正在开发的投资组合网站制作一个“Like”按钮,但我被自己的一些代码难住了!

我有两个 MySQL 表:

  • img_all:包含服务器上的所有图片(每张图片有6个INT id)
  • login:包含网站所有用户的帐户信息(每个用户有一个 6 个 INT id 以及一个标记为“likes”的 VARCHAR 列)

我的系统布局方式。当用户“喜欢”一张图片时,我将该图片的 id 保存到登录表的列中。

UPDATE login SET likes = CONCAT(likes,':$img_id:') WHERE user_key = $user_id;

当他们不喜欢一张图片时:

UPDATE login SET likes = REPLACE(likes,':$img_id:','') WHERE user_key = $user_id;

这将在 likes 列中输出类似于此的字符串:

:456093:475829:203944:789203:

我的问题从这里开始。我正在制作一个页面,允许用户查看他们喜欢的所有图片(让我们将此文件称为“Likes.php”)。 但是,喜欢的图片列表保存在login表中,而实际图片信息保存在img_all中。

我如何从我的 login 表中获取列表并将其转换为从 img_all 中选择这些图像?我正在考虑混合使用:

SELECT user_key FROM login WHERE likes LIKE '%:$img_id:%';

while();

我还想到了一个 SQL 查询。我知道这行不通。但是,希望它也有助于传达我正在努力完成的工作!

SELECT * FROM
img_all WHERE id =
      SELECT likes FROM login
            WHERE likes LIKE '%:$img_id:%' AND user_key = '$user_id';

【问题讨论】:

  • 规范化该数据,这是一个糟糕的设计。 en.wikipedia.org/wiki/First_normal_form
  • @tim 感谢您的评论!我实际上没有考虑或听说过 1NF、2NF 等!我一定会相应地重新设计我的桌子。但是,即使我这样做,我仍然会面临同样的问题......
  • 添加点赞表 (user_id,image_id) 然后您可以使用单个联接轻松显示所有用户点赞
  • SELECT * FROM img_all left join likes on img_all.id=likes.image_id WHERE user_id=XXX 这将为您提供 XXX 人喜欢的所有图像
  • 是的,每个 user_id\image_id 一行,您可以在两者上创建一个唯一键,这样您就不会得到重复项。并且不要担心你得到多少行 mysql 对数百万感到满意,这将扩展,你当前的方法不会。

标签: mysql database string join database-design


【解决方案1】:

你快到了。您可以将查询转换为JOIN,而不是使用子查询,例如:

SELECT i.*
FROM img_all i
INNER JOIN login l ON l.likes LIKE CONCAT('%:', l.img_id, ':%')
WHERE user_id = ?

虽然这可能会解决您的问题,但请注意,将值列表存储在单个列中几乎总是表明设计不佳。

访问和修改数据需要对字符串进行操作,这对SQL来说是不容易的,容易出错,效率很低。此外,正如Bill Karwin 所评论的那样,您可以为单个用户存储的点赞数受到字符串列的最大大小的限制。

正如tim 所评论的,您应该使用单独的表来存储likes,并使用loginimg_all 表的外键。

CREATE TABLE likes (
    like_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    img_id  INT NOT NULL,
    PRIMARY KEY (like_id),
    FOREIGN KEY fk_likes_login(user_id) REFERENCES login(user_id),
    FOREIGN KEY fk_likes_img(img_id) REFERENCES  img_all(img_id)
);

注意:自动递增的主键不是绝对必要的,可以用两个外键上的复合唯一索引代替。

然后您可以通过简单的JOINed 查询检索用户喜欢的所有图像:

SELECT i.*
FROM likes 
INNER JOIN img_all ON img_all.img_id = likes.img_id
WHERE likes.user_id = ?

【讨论】:

  • 你甚至不需要like_id,你将永远不会用它做什么,只需一个唯一的索引,每个索引将涵盖所有选项
  • 感谢您提供额外信息!我真的很高兴我问了,否则在我上大学之前我什至不会听说 1NF!
  • @tim :关于这个问题有不同的思想流派......但无论如何你是正确的,因为自动pk在这里并不是绝对必要的,我更新了我的答案以使其明确.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-06
  • 2011-06-07
  • 1970-01-01
  • 2017-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多