无法弄清楚如何加入这些表

时间:2010-07-14 07:50:13

标签: sql mysql

在这里需要某种加入方式的帮助。无法弄明白。

我想循环讨论论坛,但我也希望从帖子中获取last_postlast_posterid,并根据last_posterid获取用户的用户名。

这是我到目前为止(:P):

SELECT name, desc, position FROM boards b
INNER JOIN posts p ON ???
INNER JOIN users u ON ???
ORDER BY b.position ASC

非常感谢帮助。

干杯

CREATE TABLE `posts` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`posterid` int(10) unsigned NOT NULL DEFAULT '0',
`subject` varchar(255) DEFAULT NULL,
`message` text,
`posted` int(10) unsigned NOT NULL DEFAULT '0',
`edited` int(10) unsigned DEFAULT NULL,
`edited_by` int(10) unsigned NOT NULL DEFAULT '0',
`icon` varchar(255) DEFAULT NULL,
`topicid` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

CREATE TABLE `boards` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL,
`desc` varchar(255) NOT NULL,
`position` int(10) NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

CREATE TABLE `users` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(200) NOT NULL,
`password` varchar(255) NOT NULL,
`salt` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
 PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8

CREATE TABLE `topics` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`posterid` int(10) unsigned NOT NULL DEFAULT '0',
`subject` varchar(255) NOT NULL,
`posted` int(10) unsigned NOT NULL DEFAULT '0',
`last_post` int(10) unsigned NOT NULL DEFAULT '0',
`last_poster` int(10) unsigned NOT NULL DEFAULT '0',
`num_views` mediumint(8) unsigned NOT NULL DEFAULT '0',
`num_replies` mediumint(8) unsigned NOT NULL DEFAULT '0',
`closed` tinyint(1) NOT NULL DEFAULT '0',
`sticky` tinyint(1) NOT NULL DEFAULT '0',
`icon` varchar(40) DEFAULT NULL,
`boardid` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=16 DEFAULT CHARSET=utf8

5 个答案:

答案 0 :(得分:2)

假设posts.topicid引用boards.idposts.posterid引用users.id,请尝试类似

的内容
SELECT b.name, d.desc, b.position
FROM boards b
LEFT JOIN posts p
  ON b.id = p.topicid
LEFT JOIN users u
  ON (p.posterid = u.id) AND (p.posted = (SELECT MAX(sp.posted) FROM posts sp GROUP BY))
ORDER BY
  b.position ASC

另一个评论:尝试命名您的字段,以便明确它们所指的内容,例如:

CREATE TABLE `foo` (
  foo_ID UNSIGNED INTEGER NOT NULL AUTO_INCREMENT,
  -- more stuff
  PRIMARY KEY (`foo_ID`)
);

这允许您在另一个表中重复使用字段名称foo_ID,这使得在执行连接时非常变得容易。

答案 1 :(得分:0)

没有什么是突出的,所以这主要是猜测:

SELECT b.name, b.desc, b.position
FROM boards AS b
INNER JOIN posts AS p
  ON b.id = p.topicid
INNER JOIN users AS u
  ON p.posterid = u.id
ORDER BY b.position ASC

答案 2 :(得分:0)

好的,缺乏一个不能承受的架构,看起来你可以使用嵌套选择。类似的东西:

DECLARE @posts TABLE
(
    postdate datetime,
    postid int,
    boardid int
)

DECLARE @users TABLE
(
    userid int,
    username varchar(10)
)

DECLARE @boards TABLE
(
    boardid int
)


INSERT INTO @boards(boardid) VALUES (1)

INSERT INTO @users (userid, username) values (1, 'Adam')

insert into @posts (postdate, postid, boardid) values (GETDATE(), 1, 1)

SELECT b.*, p.* 
from @boards b
inner join
(
    SELECT TOP 1 postdate, postid, boardid, username FROM @posts 
    inner join @users on userid = postid WHERE boardid = 1
    order by postdate desc
) as p on p.boardid = b.boardid

显然,这是一个很大的概括并使用了一些硬编码值,但希望它可以为你提供在你自己的表上实现它的选项。

当然,我推断我的规范实现没有正确性 - SQL不是我的第一语言lol

答案 3 :(得分:0)

SELECT username, message, posts.id
FROM users, posts
WHERE posterid=users.id
GROUP BY username, message, posts.id
HAVING posted=MAX(posted)

这可能只是为了简明扼要地告诉每个用户的最后一篇文章。

答案 4 :(得分:0)

将此作为评论发布,但它过于冗长和混乱。

  1. 你会想要使用OUTER JOIN,因为否则其中没有帖子的棋盘就不会出现
  2. 任何链接这四个表的单个查询都将是一个野兽 - 考虑使用VIEW来简化事情
  3. 你的初始问题和你发布的表格让事情有些含糊不清:你们已经在主题中填写了last_post和last_poster吗?如果是这样,那么连接的主要目标应该是主板和主题,并且由于您已经存储了冗余数据(我假设速度?),为什么不同时放入last_post_time或者其他东西,这会简化事情很多和遏制负荷(根本不需要加入职位)?
  4. mediumint S'为什么在地球上? (如果你不需要日期,并且你认为它永远不会包装,我想你可以使用黑客相信后期帖子因自动增加密钥而具有更高的ID ...)