简体   繁体   English

在MySQL中运行多个查询而不使用子查询

[英]Running multiple queries in MySQL without using sub-query

I have two tables, one table called users with, 我有两个表,一个叫做users表,

fsname
emailaddress

and second table called attempts with emailaddress , score and datetime . 和第二个表调用了emailaddressscoredatetime attempts

Now what I wanted to do is first order the attempts table by datetime and then pick then join the attempt table with users table if they have same emailaddress and then pick the final attempts of each unique user. 现在我想要做的是首先按datetime排序attempts表,然后选择然后加入带有users表的attempt表,如果它们具有相同的emailaddress ,然后选择每个唯一用户的最终尝试。

In short, I have to pick the last attempt of each user by joining these table and this is the query that I have generated to achieve this, 简而言之,我必须通过加入这些表来选择每个用户的最后一次尝试,这是我为实现此目的而生成的查询,

$query = "SELECT 
            distinct users.fsname, users.emailaddress, attempts.score 
            FROM users 
            INNER JOIN attempts 
            ON users.emailaddress = attempts.emailaddress 
            ORDER BY datetime DESC";

This query first suppose to order the attempts by datetime and only pick values with distinct first name which is fsname over here. 此查询首先假设按datetimeattempts进行排序,并且仅选择具有不同名字的值,即fsname over here。

but When I execute the above query it returns the result with having non-unique values of fsname eventhough I am using DISTINCT with fsname . 但是当我执行上面的查询时,它返回的结果具有非唯一的fsname值,尽管我正在使用带有fsname DISTINCT

Can anyone please tell me why DISTINCT is not working to only pick distinct fsname ? 任何人都可以告诉我为什么DISTINCT不工作只选择不同的fsname

I have tried both DISTINCT fsname and DISTINCT(fsname) but none of these are working. 我已经尝试了DISTINCT fsnameDISTINCT(fsname)但这些都没有用。

It doesn't work as you think it should and the documentation explains the meaning of DISTINCT : it's about distinct rows : 它不会像您认为的那样工作, 文档解释了DISTINCT的含义:它是关于不同的

The ALL and DISTINCT options specify whether duplicate rows should be returned. ALLDISTINCT选项指定是否应返回重复的行。 ALL (the default) specifies that all matching rows should be returned, including duplicates. ALL (默认值)指定应返回所有匹配的行,包括重复行。 DISTINCT specifies removal of duplicate rows from the result set. DISTINCT指定从结果集中删除重复的行。 It is an error to specify both options. 指定两个选项都是错误的。 DISTINCTROW is a synonym for DISTINCT . DISTINCTROW是同义词DISTINCT

(source: http://dev.mysql.com/doc/refman/5.7/en/select.html ) (来源: http//dev.mysql.com/doc/refman/5.7/en/select.html

You need to group the rows by user in order to get a single row for each user but, unfortunately, you cannot get their most recent score this way. 您需要按用户对行进行分组,以便为​​每个用户获取一行,但遗憾的是,您无法通过这种方式获得最新的分数。 You can get the maximum, minimum, average score and other computed values. 您可以获得最大值,最小值,平均值和其他计算值。 Check the list of GROUP BY aggregate functions . 检查GROUP BY聚合函数列表。

The query 查询

This is the query that gets the values you need: 这是获取所需值的查询:

SELECT u.fsname, u.emailaddress, la.score 
FROM users u
INNER JOIN attempts la                # 'la' from 'last attempt'
    ON u.emailaddress = la.emailaddress
LEFT JOIN attempts mr                 # 'mr' from 'more recent' (than last attempt)
    ON la.emailaddress = mr.emailaddress AND la.datetime < mr.datetime
WHERE mr.datetime IS NULL

How it works 这个怎么运作

It joins table users (aliased as u ) with table attempts (aliased as la , short for "last attempt") using emailaddress as the matching column. 它使用emailaddress作为匹配列,将表users (别名为u )与表attempts (别名为la ,“最后一次尝试”的缩写)连接起来。 It's the join you already have in your query, I added the aliases because they help you write less from that point on. 这是你在查询中已经拥有的连接,我添加了别名,因为它们可以帮助你减少从那一点开始写的内容。

Next, it joins the attempts table again (aliased as mr from " more recent than the last attempt"). 接下来,加入attempts再次表(别名为mr从“比上一次尝试更近 ”)。 It matches each attempt from la with all the attempts from mr of the same user (identified by their emailaddress ) and that have a more recent datetime . 它匹配来自la每次尝试以及来自同一用户的mr (由他们的emailaddress标识)的所有尝试并且具有更新的datetime The LEFT JOIN ensures that each row from la matches at least one row from mr . LEFT JOIN确保la中的每一行与mr至少一行匹配。 The rows from la that do not have a match in mr are the rows that have the biggest values of datetime for each emailaddress . la中没有匹配的行是mr是每个emailaddress具有最大datetime值的行。 They are matched with rows full of NULL (for the mr part). 它们与满NULL行匹配(对于mr部分)。

Finally, the WHERE clause keeps only the rows that have NULL in the datetime column of the row selected from mr . 最后, WHERE子句仅保留从mr选择的行的datetime列中具有NULL的行。 These are the rows that matched the most recent entries from la for each value of emailaddress . 这些是与emailaddress每个值匹配la最新条目的行。

Performance remarks 表现评论

In order to run fast this query ( any query! ) needs indexes on the columns used in the JOIN , WHERE , GROUP BY and ORDER BY clauses. 为了快速运行此查询( 任何查询! )需要在JOINWHEREGROUP BYORDER BY子句中使用的列上的索引。

You should not use emailaddress in table attempts to identify the user. 您不应在表attempts使用emailaddress来识别用户。 You should have a PK (primary key) on table users and use that as a FK (foreign key) in table attempts (and other tables that refer to a user). 您应该在表users使用PK (主键),并在表attempts (以及引用用户的其他表)中将其用作FK (外键)。 If emailaddress is the PK of table users change it to an UNIQUE INDEX and use a new INTEGER AUTO INCREMENT ed column userId as PK instead. 如果emailaddress是表的users PK ,则将其更改为UNIQUE INDEX并使用新的INTEGER AUTO INCREMENT ed列userId作为PK The indexes on numeric columns are faster and use less space than the indexes on string columns. 数字列上的索引比字符串列上的索引更快,占用的空间更少。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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