加入两个表mysql,一对多关系

时间:2013-03-17 18:32:35

标签: mysql sql join aggregate-functions

我有两张桌子:

积分 - >

id           bigint(20)   NO   PRI  NULL   auto_increment
created_at   datetime     NO        NULL   
ip           varchar(255) NO        NULL   
item_id      bigint(20)   NO   MUL  NULL   
updated_at   timestamp    YES       NULL   

和项目 - >

id           bigint(20)    NO  PRI  NULL   auto_increment
author       varchar(255)  NO       NULL   
created_at   datetime      NO       NULL   
description  varchar(255)  NO       NULL   
link         varchar(255)  NO       NULL   
source       varchar(255)  NO       NULL   
title        varchar(180)  NO       NULL   
url_encoded  varchar(255)  NO  UNI  NULL   
updated_at   timestamp     YES      NULL   

我希望在一个查询中加入他们,所以我会得到item.*以及相对于它们的总数。我也想这样做只适用于在过去24小时内为它们创建任何点的项目。

这是我目前的查询:

SELECT `items`.*, COUNT(points.item_id) as points
FROM `items`
INNER JOIN `points` ON `items`.`id` = `points`.`item_id`
WHERE `points`.`created_at` > '2013-03-16 16:00:14'
ORDER BY points DESC
LIMIT 30;

不幸的是,当它应该是一个时,它应该只有两行,有两个点。在我的数据库中,每个项目有两个项目和一个点。请帮我解决这个问题,并了解如何改进我的查询以获得结果。

3 个答案:

答案 0 :(得分:2)

SELECT i.*, count(*) AS point_ct
FROM   items  i
JOIN   points p ON p.item_id = i.id
GROUP  BY i.id
HAVING MAX(created_at) >= DATE_SUB(CURDATE(), INTERVAL 1 day)
ORDER  BY point_ct DESC
LIMIT  30;

我引用the manual concerning the GROUP BY clause

  

MySQL扩展了GROUP BY的使用,允许选择字段   在GROUP BY子句中没有提到。如果你没有得到   您希望从查询中得到的结果,请阅读说明   在{中找到GROUP BY   Section 12.17, “Functions and Modifiers for Use with GROUP BY Clauses”

标准SQL需要列出SELECT中所有未组合的GROUP BY项 但是,该标准还定义了“功能相关”列自动覆盖。由于我们按id分组主键,因此最终成为标准SQL(LIMIT 30除外,FETCH FIRST 30 ROWS ONLY为{{1}}标准SQL)。

答案 1 :(得分:2)

您需要使用GROUP BY来解释基于哪些分组。没有GROUP BY,您只需获得整个结果集的一组,如您所见。

在标准SQL中,有必要在GROUP BY子句中包含SELECT子句中包含的每个非聚合表达式,但MySQL允许您不执行此操作,允许表达式下列。 (至少,当没有处于严格模式时;我不确定严格模式是否会强化此要求以匹配标准SQL)

SELECT `items`.*, COUNT(1) AS points
FROM `items` INNER JOIN `points` ON `items`.`id` = `points`.`item_id`
WHERE ...
GROUP BY `items`.`id`

假设items.id是此表的主键,因此它不会出现在items的多行中,这应该会产生预期效果。

介绍GROUP BY后,了解WHEREHAVING条款之间的区别非常重要。前者应用条件之前组并应用聚合,而后者应用之后。这意味着如果您想根据该计数执行条件,则必须使用HAVING;初始示例中的WHERE子句将在聚合之前应用,因此结果将是在给定日期之后创建的点数。

答案 2 :(得分:0)

创建一个表链接。使用字段iditemidpointsid

输入:

Row1: 1, items-id1, points-id-1
Row2: 2, items-id-1, points-id-2
Row3: 3, items-id-1, points-id-3
SELECT * FROM points, field WHERE tablelink.itemid=items.id AND tablelink.pointsid=points.id;

一个项目有很多要点。