简体   繁体   English

连接两个表mysql,一对多关系

[英]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 ,了解WHEREHAVING子句之间的区别很重要。 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 the GROUP BY clause. MySQL 扩展了GROUP BY的使用,以允许选择GROUP BY子句中未提及的字段。 If you are not getting the results that you expect from your query, please read the description of GROUP 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使用字段iditemidpointsid

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM