MySQL:如何在执行3向左连接时使用COUNT?

时间:2015-04-10 19:17:00

标签: mysql

我正在执行3向左连接以检索邮件信息。除了消息,我还想要每条消息的投票数。消息的每个投票都由投票表中的条目表示。我想返回所有消息和标记信息以及给定消息在投票表中的条目数。

查询

 var query = ([
        'SELECT * FROM marks',
        'LEFT JOIN messages',
          'ON marks.messageId = messages.id',
        'LEFT JOIN votes',
          'ON votes.messageId = messages.id',
        'WHERE marks.x between ? AND ?',
          'AND marks.y between ? AND ?',
        'ORDER BY timestamp DESC'
    ]).join(' ');

模式

CREATE TABLE marks (
  id int(5) AUTO_INCREMENT,
  PRIMARY KEY (id),
  x float(10, 6),
  y float(10, 6),
  z float(10, 6),
  timestamp timestamp DEFAULT CURRENT_TIMESTAMP,
  messageId int(5),
  FOREIGN KEY (messageId) REFERENCES messages(id),
  userToken VARCHAR(255),
  FOREIGN KEY (userToken) REFERENCES users(token)
);

CREATE TABLE messages (
  id int(5) AUTO_INCREMENT,
  PRIMARY KEY (id),
  messageString text,
  score int(5) DEFAULT 0
);

CREATE TABLE votes (
  id int(5) AUTO_INCREMENT,
  PRIMARY KEY(id),
  userToken VARCHAR(255),
  FOREIGN KEY (userToken) REFERENCES users(token),
  messageId int(5),
  FOREIGN KEY (messageId) REFERENCES messages(id)
);

示例数据:

mysql> select * from marks;
+----+------------+-------------+------------+---------------------+-----------+-----------+
| id | x          | y           | z          | timestamp           | messageId | userToken |
+----+------------+-------------+------------+---------------------+-----------+-----------+
|  3 |  37.783600 | -122.408974 |  69.000000 | 2015-04-08 16:15:27 |         3 | NULL      |
|  6 | 535.000000 |  325.000000 | 325.000000 | 2015-04-09 14:36:39 |         6 | live      |
|  7 | 535.000000 |  325.000000 | 325.000000 | 2015-04-09 14:40:10 |         7 | live      |
|  8 | 535.000000 |  325.000000 | 325.000000 | 2015-04-09 14:41:00 |         8 | live      |
|  9 | 535.000000 |  325.000000 | 325.000000 | 2015-04-09 14:41:42 |         9 | live      |
| 10 | 535.000000 |  325.000000 | 325.000000 | 2015-04-09 14:43:44 |        10 | live      |
+----+------------+-------------+------------+---------------------+-----------+-----------+
6 rows in set (0.00 sec)

mysql> select * from messages;
+----+--------------------+-------+
| id | messageString      | score |
+----+--------------------+-------+
|  3 | Brooks was here    |  9001 |
|  4 | NULL               |     0 |
|  5 | NULL               |     0 |
|  6 | NULL               |     0 |
|  7 | NULL               |     0 |
|  8 | OMG I LOVE JALEPNO |     0 |
|  9 | OMG I LOVE JALEPNO |     0 |
| 10 | OMGEE BEEBEEQUE    |   100 |
+----+--------------------+-------+
8 rows in set (0.00 sec)

mysql> select * from votes;
+----+-----------+-----------+
| id | userToken | messageId |
+----+-----------+-----------+
|  2 | grgrdg    |         3 |
|  3 | live      |         3 |
|  5 | live      |        10 |
|  6 | live      |        10 |
|  7 | live      |        10 |
|  8 | live      |        10 |
|  9 | live      |        10 |
| 10 | live      |         9 |
| 11 | live      |         9 |
| 12 | live      |         9 |
+----+-----------+-----------+
10 rows in set (0.00 sec)

3 个答案:

答案 0 :(得分:1)

如果您当前的查询适合您。 我无法识别您使用的语言。

但是在普通的mysql中你可以做类似的事情:

SELECT marks.*, messages.messageString , votes.votes_counter 
FROM marks
LEFT JOIN messages
 ON marks.messageId = messages.id
LEFT JOIN (
  SELECT messageId, COUNT(*) as votes_counter 
  FROM votes
  GROUP BY messageId
  ) as votes
 ON votes.messageId = messages.id
WHERE marks.x between ? AND ?
 AND marks.y between ? AND ?
ORDER BY timestamp DESC

答案 1 :(得分:1)

首先编写每个消息的投票数的子查询。为此,您只需要投票表:

SELECT messageId, COUNT(*) AS numVotes
FROM votes
GROUP BY messageId;

一旦你有了,外部将它连接到其他表,并使用COALESCE()将空的投票计数消息替换为0:

SELECT m.*, ms.*, COALESCE(t.numVotes, 0)
FROM marks m
LEFT JOIN messages ms ON ms.messageId = m.messageId
LEFT JOIN (
   SELECT messageId, COUNT(*) AS numVotes
   FROM votes
   GROUP BY messageId) t ON t.messageId = ms.messageId;

答案 2 :(得分:1)

使用COUNT(votes.id)GROUP BY marks.id, messages.id

通过计票,如果该消息没有投票,你将获得0票

SELECT  marks.id
,       marks.x
,       marks.y
,       marks.z
,       marks.timestamp
,       marks.messageId
,       marks.userToken
,       messages.messageString
,       messages.score
,       COUNT(votes.id)
FROM    marks
LEFT JOIN messages ON messages.id = marks.messageId
LEFT JOIN votes ON votes.messageId = messages.id
GROUP BY marks.id, messages.id