[英]Join two tables mysql, one to many relationship
I have two tables:我有两个表:
Points ->积分 ->
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
and Items ->和项目 ->
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
I want to join them hopefully in one query so I will get item.*
and the total of how many points are relative to them.我希望在一个查询中加入他们,这样我就会得到
item.*
以及与它们相关的总点数。 I also want to do this only for the items that has any points created for them in the last 24 hours.我还想仅针对在过去 24 小时内为它们创建了任何积分的项目执行此操作。
This is my query so far:到目前为止,这是我的查询:
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;
Unfortunately it gives me only one row when it should be two with two points when it should be one.不幸的是,当它应该是两个时,它只给了我一行,而当它应该是一个时,它给了我两个点。 In my database there is two items and one point for each of them.
在我的数据库中有两个项目,每个项目都有一个点。 Please help me fix this and understand how I can improve my query to get both the results.
请帮我解决这个问题,并了解如何改进我的查询以获得两个结果。
You need to use GROUP BY
to explain what groupings to count based on.您需要使用
GROUP BY
来解释要基于哪些分组进行计数。 Without GROUP BY
you just get a single group of the entire result set, as you saw.如您所见,如果没有
GROUP BY
您只会得到整个结果集的单个组。
In standard SQL it is necessary to include in the GROUP BY
clause every non-aggregate expression that's included in the SELECT
clause, but MySQL lets you get away with not doing this, allowing an expression like the following.在标准 SQL 中,有必要在
GROUP BY
子句中包含SELECT
子句中包含的每个非聚合表达式,但 MySQL 允许您不这样做,允许使用如下所示的表达式。 (At least, when not in strict mode; I'm not sure if strict mode strengthens this requirement to match standard SQL) (至少,当不在严格模式下时;我不确定严格模式是否加强了这一要求以匹配标准 SQL)
SELECT `items`.*, COUNT(1) AS points
FROM `items` INNER JOIN `points` ON `items`.`id` = `points`.`item_id`
WHERE ...
GROUP BY `items`.`id`
Assuming that items.id
is the primary key of this table, and so it won't appear in more than one row of items
, this should have the desired effect.假设
items.id
是这个表的主键,所以它不会出现在超过一行的items
,这应该会达到预期的效果。
Once you introduce GROUP BY
it's important to understand the difference between the WHERE
and HAVING
clauses.介绍
GROUP BY
,了解WHERE
和HAVING
子句之间的区别很重要。 The former applies the condition before the group and aggregates are applied, while the latter applies afterwards .前者适用于组和聚合之前的条件,而后者适用于之后。 This means you must use
HAVING
if you want to do a conditional based on that count;这意味着如果您想根据该计数执行条件,则必须使用
HAVING
; the WHERE
clause in your initial example will apply before the aggregate, so the result will be the count of points created after the given date.初始示例中的
WHERE
子句将在聚合之前应用,因此结果将是给定日期之后创建的点数。
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;
I quote the manual concerning the GROUP BY
clause :我引用了有关
GROUP BY
子句的手册:
MySQL extends the use of
GROUP BY
to permit selecting fields that are not mentioned in theGROUP BY
clause.MySQL 扩展了
GROUP BY
的使用,以允许选择GROUP BY
子句中未提及的字段。 If you are not getting the results that you expect from your query, please read the description ofGROUP BY
found in如果您没有从您的查询中得到您期望的结果,请阅读
GROUP BY
的说明
Section 12.17, “Functions and Modifiers for Use with GROUP BY Clauses” .第 12.17 节,“与 GROUP BY 子句一起使用的函数和修饰符” 。
Standard SQL would require to list all ungrouped SELECT
items in GROUP BY
.标准 SQL 需要在
GROUP BY
列出所有未分组的SELECT
项。
However, the standard also defines that "functionally dependent" columns are covered automatically.但是,该标准还定义了自动涵盖“功能相关”列。 Since we are grouping by
id
which is the primary key , this ends up to be standard SQL after all (except for LIMIT 30
, which would be FETCH FIRST 30 ROWS ONLY
in standard SQL).由于我们按
id
分组,这是主键,这毕竟是标准 SQL(除了LIMIT 30
,它在标准 SQL 中将是FETCH FIRST 30 ROWS ONLY
)。
Create a table link.创建表链接。 With the fields
id
, itemid
, pointsid
使用字段
id
、 itemid
、 pointsid
Inputs:输入:
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;
One item has many points.一个项目有很多点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.