如何避免这种复杂的查询?

时间:2012-05-17 19:36:00

标签: mysql database database-design

我正在设计一个像pinterest(用于学习)的网站,我想知道在主页上我要做什么查询来显示用户的流。

我创建了这6个表:

users
boards
pictures
boards_pictures ( many-to-many table )
followers
comments

在家中,我会通过此查询获取所有粉丝的照片。

SELECT users.username, pictures.link, comments.comment, boards.title
FROM boards_pictures, pictures, followers, users, comments, boards 
WHERE ( boards_pictures.id_user = followers.id_following ) 
  AND ( boards_pictures.id_picture = pictures.id ) 
  AND ( followers.id_user = $_session['userid'] ) 
  AND ( users.id = followers.id_following )
  AND ( comments.picture_id = pictures.id )
  AND ( boards.id = boards_pictures.boards_id )

有没有办法避免这种复杂的查询(带有6个表的JOIN)?

2 个答案:

答案 0 :(得分:1)

它实际上是一个非常简单的查询,只有很多表。

我不会尝试检索一个大查询中的所有内容,这会导致输出中出现大量重复数据,而是执行一次查询以检索用户/电路板/图片信息,另一次查询关注者,另一次查询评论。

此外,您可以使用ANSI语法以提高可读性。

答案 1 :(得分:1)

以下是从您的查询中推断出的DDL语句:

CREATE TABLE users (id integer, username varchar(30));
CREATE TABLE boards (id integer, title varchar(30));
CREATE TABLE pictures (id integer, link varchar(90));
CREATE TABLE boards_pictures (
  id_user integer,
  id_picture integer,
  boards_id integer);
CREATE TABLE followers (id_user integer, id_following integer);
CREATE TABLE comments (picture_id integer, comment varchar(350));

您在此处混合列命名样式,比较users.idfollowers.id_usercomments.picture_idboard_pictures.id_picture(最后2个具有误导性)。您拥有的表越多,您对列的命名方式就越需要注意。最好坚持使用单一的共同模式,picture_iduser_id在我看来最合适。

除了使用implicit join notation之外,您的查询并不复杂。这不是推荐的方式,因为有机会错过一些谓词并最终得到Cartesian product个2(或更多)表。

您的查询可以像这样重写:

SELECT u.username, p.link, c.comment, b.title
  FROM boards_pictures bp
  JOIN pictures p ON p.id = bp.id_picture
  JOIN followers f ON bp.id_user = f.id_following
  JOIN users u ON u.id = f.id_following
  JOIN comments c ON c.picture_id = p.id
  JOIN boards b ON b.id = bp.boards_id
WHERE f.id_user = $_session['userid'];

如您所见,查询非常简单,只有一个谓词。 我在SQL Fiddle创建了一个没有数据的测试平台。

在我看来,你的结构非常好。无需更改表格设计或此查询。