运行 MySQL 中的多个查询未使用子查询
Running multiple queries in MySQL without using sub-query
我有两个 table,
一个 table 叫 users
,
fsname
emailaddress
和第二个 table 用 emailaddress
、score
和 datetime
.
调用了 attempts
现在我想做的是先用 datetime
订购 attempts
table 然后选择然后加入 attempt
table 和 users
table 如果他们有相同的 emailaddress
然后选择每个唯一用户的最终尝试。
简而言之,我必须通过加入这些 table 来选择每个用户的最后一次尝试,这是我为实现此目的而生成的查询,
$query = "SELECT
distinct users.fsname, users.emailaddress, attempts.score
FROM users
INNER JOIN attempts
ON users.emailaddress = attempts.emailaddress
ORDER BY datetime DESC";
此查询首先假设按 datetime
对 attempts
进行排序,并且仅选择具有不同名字的值,即此处的 fsname
。
但是当我执行上面的查询时它 returns 结果具有非唯一值 fsname
尽管我使用 DISTINCT
和 fsname
.
谁能告诉我为什么 DISTINCT
不能只选择不同的 fsname
吗?
我已经尝试了 DISTINCT fsname
和 DISTINCT(fsname)
,但其中 none 有效。
它没有像您认为的那样工作,documentation 解释了 DISTINCT
的含义:它是关于不同的 行:
The ALL
and DISTINCT
options specify whether duplicate rows should be returned. ALL
(the default) specifies that all matching rows should be returned, including duplicates. DISTINCT
specifies removal of duplicate rows from the result set. It is an error to specify both options. DISTINCTROW
is a synonym for DISTINCT
.
(来源:http://dev.mysql.com/doc/refman/5.7/en/select.html)
您需要按用户对行进行分组,以便为每个用户获得一行,但不幸的是,您无法通过这种方式获得他们的最新分数。
您可以获得最大、最小、平均分数和其他计算值。查看 GROUP BY
aggregate functions.
的列表
查询
这是获取所需值的查询:
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
工作原理
它加入table users
(别名u
)和table attempts
(别名la
,"last attempt") 使用 emailaddress
作为匹配列。这是您在查询中已有的联接,我添加了别名,因为它们可以帮助您从那时起减少编写。
接下来,它再次加入 attempts
table(别名为 mr
,来自“比上次尝试更近”)。它将来自 la
的每次尝试与来自同一用户(由他们的 emailaddress
标识) 和 的所有尝试进行匹配,这些尝试具有更新的datetime
。 LEFT JOIN
确保来自 la
的每一行至少匹配来自 mr
的一行。 la
中未在 mr
中匹配的行是每个 emailaddress
具有最大值 datetime
的行。它们与充满 NULL
的行匹配(对于 mr
部分)。
最后,WHERE
子句仅保留从 mr
中选择的行的 datetime
列中具有 NULL
的行。对于 emailaddress
.
的每个值,这些行与 la
中的最新条目相匹配
性能备注
为了 运行 快速查询(任何查询!)需要在 JOIN
、WHERE
中使用的列上建立索引, GROUP BY
和 ORDER BY
子句。
您不应在 table attempts
中使用 emailaddress
来识别用户。您应该在 table users
上有一个 PK
(主键),并将其用作 table attempts
中的 FK
(外键)(和其他引用用户的 table)。如果 emailaddress
是 table 的 PK
users
将其更改为 UNIQUE INDEX
并使用新的 INTEGER AUTO INCREMENT
ed 列 userId
作为PK
代替。与字符串列上的索引相比,数字列上的索引更快并且使用更少 space。
我有两个 table,
一个 table 叫 users
,
fsname
emailaddress
和第二个 table 用 emailaddress
、score
和 datetime
.
attempts
现在我想做的是先用 datetime
订购 attempts
table 然后选择然后加入 attempt
table 和 users
table 如果他们有相同的 emailaddress
然后选择每个唯一用户的最终尝试。
简而言之,我必须通过加入这些 table 来选择每个用户的最后一次尝试,这是我为实现此目的而生成的查询,
$query = "SELECT
distinct users.fsname, users.emailaddress, attempts.score
FROM users
INNER JOIN attempts
ON users.emailaddress = attempts.emailaddress
ORDER BY datetime DESC";
此查询首先假设按 datetime
对 attempts
进行排序,并且仅选择具有不同名字的值,即此处的 fsname
。
但是当我执行上面的查询时它 returns 结果具有非唯一值 fsname
尽管我使用 DISTINCT
和 fsname
.
谁能告诉我为什么 DISTINCT
不能只选择不同的 fsname
吗?
我已经尝试了 DISTINCT fsname
和 DISTINCT(fsname)
,但其中 none 有效。
它没有像您认为的那样工作,documentation 解释了 DISTINCT
的含义:它是关于不同的 行:
The
ALL
andDISTINCT
options specify whether duplicate rows should be returned.ALL
(the default) specifies that all matching rows should be returned, including duplicates.DISTINCT
specifies removal of duplicate rows from the result set. It is an error to specify both options.DISTINCTROW
is a synonym forDISTINCT
.
(来源:http://dev.mysql.com/doc/refman/5.7/en/select.html)
您需要按用户对行进行分组,以便为每个用户获得一行,但不幸的是,您无法通过这种方式获得他们的最新分数。
您可以获得最大、最小、平均分数和其他计算值。查看 GROUP BY
aggregate functions.
查询
这是获取所需值的查询:
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
工作原理
它加入table users
(别名u
)和table attempts
(别名la
,"last attempt") 使用 emailaddress
作为匹配列。这是您在查询中已有的联接,我添加了别名,因为它们可以帮助您从那时起减少编写。
接下来,它再次加入 attempts
table(别名为 mr
,来自“比上次尝试更近”)。它将来自 la
的每次尝试与来自同一用户(由他们的 emailaddress
标识) 和 的所有尝试进行匹配,这些尝试具有更新的datetime
。 LEFT JOIN
确保来自 la
的每一行至少匹配来自 mr
的一行。 la
中未在 mr
中匹配的行是每个 emailaddress
具有最大值 datetime
的行。它们与充满 NULL
的行匹配(对于 mr
部分)。
最后,WHERE
子句仅保留从 mr
中选择的行的 datetime
列中具有 NULL
的行。对于 emailaddress
.
la
中的最新条目相匹配
性能备注
为了 运行 快速查询(任何查询!)需要在 JOIN
、WHERE
中使用的列上建立索引, GROUP BY
和 ORDER BY
子句。
您不应在 table attempts
中使用 emailaddress
来识别用户。您应该在 table users
上有一个 PK
(主键),并将其用作 table attempts
中的 FK
(外键)(和其他引用用户的 table)。如果 emailaddress
是 table 的 PK
users
将其更改为 UNIQUE INDEX
并使用新的 INTEGER AUTO INCREMENT
ed 列 userId
作为PK
代替。与字符串列上的索引相比,数字列上的索引更快并且使用更少 space。