有关创建SQL连接的建议

时间:2013-04-14 21:38:57

标签: mysql sql join

我很难获得一个查询来产生我需要的行,要么提供太多或太多的重复项。

最终,我想要的是一个查询,它产生所有非重复资源,其中cid> 0

我研究了其他答案,但大多数只是提供一个有效的查询。我希望答案能帮助我和其他人更好地理解查询构建。谢谢!

TL; DR版本跟随......

以下查询会产生重复项:

SELECT DISTINCTROW r.rid, r.rname, c.cid, c.spanclass, c.cname, u.name, r.time
FROM rmn_resources as r, rmn_users as u, rmn_conditions as c
WHERE c.cid=r.cid

以下是我展示数据的尝试:

|r.rid  |r.rname        |c.cid  |c.spanclass        |c.cname        |u.name |r.time
|1      |'Keyfob #1'    |0      |NULL               |'Created'      |User B |'0000-00-00 00:00:00'
|1      |'Keyfob #1'    |0      |NULL               |'Created'      |User A |'0000-00-00 00:00:00'
|2      |'Keyfob #2'    |1      |'label-success'    |'Available'    |User B |'2013-04-13 02:17:07'
|2      |'Keyfob #2'    |1      |'label-success'    |'Available'    |User A |'2013-04-13 02:17:07'
|3      |'Keyfob #3'    |2      |'label-important'  |'Checked out'  |User B |'2013-04-13 18:11:17'
|3      |'Keyfob #3'    |2      |'label-important'  |'Checked out'  |User A |'2013-04-13 18:11:17'
|5      |'Spork'        |1      |'label-success'    |'Available'    |User B |'2013-04-14 02:29:39'
|5      |'Spork'        |1      |'label-success'    |'Available'    |User A |'2013-04-14 02:29:39'

我有一个减少重复的变体,但仍然有两个记录,我只想要一个:

SELECT DISTINCTROW r.rid, r.rname, c.cid, c.spanclass, c.cname, u.name, r.time
FROM rmn_resources as r, rmn_users as u, rmn_conditions as c
WHERE c.cid=r.cid AND (u.uid=r.uid OR (r.uid=0 AND r.cid>0))

另一个不会产生重复,但不会显示我心爱的Spork。

SELECT DISTINCTROW r.rid, r.rname, c.cid, c.spanclass, c.cname, u.name, r.time
FROM rmn_resources as r, rmn_users as u, rmn_conditions as c
WHERE c.cid=r.cid AND u.uid=r.uid

(老实说,我在黑暗中拍摄,试图纠缠查询。)

以下是SQL格式的基本表格(道歉没有TL; DR版本)

表:rmn_resources

CREATE TABLE IF NOT EXISTS `rmn_resources` (
  `rid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `rname` varchar(255) CHARACTER SET utf8 NOT NULL,
  `oid` int(10) unsigned NOT NULL COMMENT 'owner uid in users',
  `cid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'cid: condition id in conditions',
  `time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT 'NULL or last changed time',
  `uid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'user uid from users',
  PRIMARY KEY (`rid`) ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

INSERT INTO `rmn_resources` (`rid`, `rname`, `oid`, `cid`, `time`, `uid`) VALUES
(1, 'Keyfob #1', 0, 0, '0000-00-00 00:00:00', 0),
(2, 'Keyfob #2', 0, 1, '2013-04-13 08:17:07', 1),
(3, 'Keyfob #3', 0, 2, '2013-04-14 00:11:17', 2),
(5, 'Spork', 1, 1, '2013-04-14 08:29:39', 0);

表:rmn_users

CREATE TABLE IF NOT EXISTS `rmn_users` (
  `uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 NOT NULL,
  `email` varchar(255) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`uid`),
  UNIQUE KEY `email` (`email`),
  KEY `name` (`name`) ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

INSERT INTO `rmn_users` (`uid`, `name`, `email`) VALUES
(1, 'User A', 'usera@users.com'),
(2, 'User B', 'userb@users.com');

表:rmn_conditions

CREATE TABLE IF NOT EXISTS `rmn_conditions` (
  `cid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `cname` varchar(255) CHARACTER SET utf8 NOT NULL,
  `spanclass` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
PRIMARY KEY (`cid`) ) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;

INSERT INTO `rmn_conditions` (`cid`, `cname`, `spanclass`) VALUES
(0, 'Created', NULL),
(1, 'Available', 'label-success'),
(2, 'Checked out', 'label-important');

2 个答案:

答案 0 :(得分:0)

您应该开始使用显式连接,重复的问题是因为您是交叉连接。最后一个查询没问题,但它没有显示spork,因为你没有匹配的用户。您可以使用LEFT JOIN,但是这样:

SELECT r.rid, r.rname, c.cid, c.spanclass, c.cname, u.name, r.time
FROM rmn_resources AS r
LEFT JOIN rmn_users AS u
  ON u.uid=r.uid
LEFT JOIN rmn_conditions AS c
  ON c.cid=r.cid;

http://sqlfiddle.com/#!8/4d5de/1

答案 1 :(得分:0)

如果您还没有加入,可能需要通读Visual-Representation-of-SQL-Joins以更好地了解联接。

当表包含数百万行时,与当前使用的连接相比,当您使用特定连接时,它会为您提供巨大的优势,内存和时间。

希望它有所帮助。

enter image description here