使用最小列值创建左连接?

时间:2014-11-16 21:58:56

标签: mysql join greatest-n-per-group

我有两个表,我想从评论表中选择作者为usr1的所有行,并将其连接到threadid和tid列匹配的posts表,但使用MIN(positionID)。< / p>

这是我的评论表:

cid     tID         author     
 1   |    1      |  usr1     |    
 2   |    2      |  usr2     |    
 3   |    3      |  usr1     |   
 4   |    3      |  usr1     |    

帖子表:

 id   threadID    rating        positionID
 1   |    1      |  99.99      |   1
 2   |    1      |  150.00     |   2
 3   |    2      |  33.10      |   1
 4   |    2      |  10.00      |   2
 5   |    3      |  16.00      |   1
 6   |    3      |  45.00      |   2
 7   |    3      |  75.00      |   3

预期结果:

cid     tID         author    rating 
 1   |    1      |  usr1     |    99.99
 3   |    3      |  usr1     |    16.00
 4   |    3      |  usr1     |    16.00

我在一些阅读后尝试了几个不同的查询,如下面的这个,但我在几行中得到NULL:

SELECT * FROM Reviews AS R
LEFT JOIN (SELECT * from posts GROUP BY positionID) AS P on P.threadID=R.tID
WHERE c.author_name='usr1'

也许左连接不是我需要的?

2 个答案:

答案 0 :(得分:1)

左连接不适合在这里使用。如果要从一个表中获取所有行,并且在匹配时仅从另一个表中获取行,则使用外部联接。在这里看来,您只想获得两个表中都存在相应行的行。

你可以从写这个开始,得到你想要的行:

SELECT r.*
FROM reviews r
JOIN posts p ON p.threadid = r.tid
WHERE r.author = 'usr1';

至于获得最低位置 - 如果它从1开始,它可能总是1,所以你可以过滤它。这应该让你有这个问题:

SELECT r.cid, r.tid, r.author, p.rating
FROM reviews r
JOIN posts p ON p.threadid = r.tid
WHERE r.author = 'usr1' AND p.positionid = 1;

但是,如果你想获得最低位置ID,我会做以下事情,虽然这看起来有点棘手但可能有更好的方法:

获取组中的第一项是一个小技巧。在这种情况下,您需要threadid组中最早的positionid:

SELECT *
FROM posts p
WHERE(
  SELECT COUNT(*)
  FROM posts pt
  WHERE pt.threadid = p.threadid AND pt.positionid <= p.positionid
  ) <= 1;

您可以使用该子查询加入评论表,如下所示:

SELECT r.cid, r.tid, r.author, t.rating
FROM reviews r
JOIN(SELECT *
  FROM posts p
  WHERE(
    SELECT COUNT(*)
    FROM posts pt
    WHERE pt.threadid = p.threadid AND pt.positionid <= p.positionid
  ) <= 1) t
ON t.threadid = r.tid AND r.author = 'usr1';

这可以在SQL Fiddle中使用,但我建议先在整个数据集上进行测试。

注意以上内容与您的结果集略有不同,因为我使用了您的想法并删除了一个positionID为1的行,以确保使用下一行。它按预期工作。

答案 1 :(得分:0)

DROP TABLE IF EXISTS posts;

CREATE TABLE posts(
  id INT NOT NULL AUTO_INCREMENT,
  threadID INT NOT NULL,
  rating DECIMAL(5,2) NOT NULL,
  positionID INT NOT NULL,
  PRIMARY KEY(id));

INSERT INTO posts(threadid, rating, positionid) VALUES
(1, 99.99, 1),
(1, 150.00, 2),
(2, 33.10, 1),
(2, 10.00, 2),
(3, 45.00, 2),
(3, 75.00, 3);

DROP TABLE IF EXISTS reviews;

CREATE TABLE reviews(
  cid INT NOT NULL AUTO_INCREMENT,
  tid INT NOT NULL,
  author VARCHAR(10) NOT NULL,
  PRIMARY KEY(cid));

INSERT INTO reviews(tid, author) VALUES
(1, 'usr1'),
(2, 'usr2'),
(3, 'usr1'),
(3, 'usr1');

SELECT cid,tid,author,rating
  FROM posts p
  JOIN
     ( SELECT threadid,MIN(positionid) min_positionid FROM posts GROUP BY threadid) x
    ON x.threadid = p.threadid
   AND x.min_positionid = p.positionid
  JOIN reviews r ON r.tid = p.threadid
 WHERE author = 'usr1'
;
+-----+-----+--------+--------+
| cid | tid | author | rating |
+-----+-----+--------+--------+
|   1 |   1 | usr1   |  99.99 |
|   3 |   3 | usr1   |  45.00 |
|   4 |   3 | usr1   |  45.00 |
+-----+-----+--------+--------+

http://sqlfiddle.com/#!2/b2669/7