在我的mysql查询中出现DISTINCT问题

时间:2015-03-18 15:44:04

标签: mysql sql

您好我想创建一个我想要相册的网站。

事情是这个网站将有2个表,1个表存储相册的名称(TBLalbum)和该相册的唯一ID(idalbumname)。 第二个表格(TBLphotos)存储有关已上传照片的信息以及每张照片所属的相册(albumidphotoname以及更多列)。 现在我想列出所有不太难做的专辑名称,但是在相同的sql查询中我希望它显示每张专辑中的第一张照片。

我试过了:

SELECT DISTINCT albumid 
FROM TBLphotos INNER JOIN TBLalbum 
ON TBLalbum.id=TBLphotos.albumid

这不能让我打印出专栏photoname

如果我包括它:

SELECT DISTINCT albumid,photoname 
FROM TBLphotos INNER JOIN TBLalbum 
ON TBLalbum.id=TBLphotos.albumid

然后它只在distinct上获得albumid

我有点难以解释,但有谁能告诉我如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

尝试:

SELECT
  a.albumid,
  a.albumname,
  (SELECT photoname FROM TBLphotos p WHERE p.albumid = a.id LIMIT 1) AS photoname
FROM TBLalbum a

子查询将每个专辑的结果集限制为只有一个带有LIMIT子句的记录。如果您想要TBLphotos中的特定记录,则可以修改子查询以按照特定顺序放置内容或执行您需要执行的任何操作。

请注意DISTINCT用于过滤掉重复的行,这不是(我认为)你真正想要做的事情。

答案 1 :(得分:1)

您的请求的正确查询是:

SELECT a.albumid, f.photoname 
FROM TBLalbum a
    INNER JOIN TBLphotos f          # "f" from "first" photo
      ON f.albumid = a.id           #          of this album
    LEFT JOIN TBLphotos o           # "o" from "other" photo
      ON o.albumid = f.albumid      #          of the same album
      AND o.photoid < f.photoid     # "o" is before "f"
WHERE o.photoid IS NULL             # no such "o" exists

解释

此查询将来自&#34;相册&#34;)的TBLalbum别名为aTBLphotos(别名为f来自&#34;这张专辑的照片&#34;)。由于INNER JOIN,没有照片的相册会包含。如果您想要包含LEFT JOIN,请使用TBLalbum

接下来,它再次加入表o(别名为o.albumid = f.albumid来自&#34;其他照片&#34;)。第一个加入条件(o)可确保从f中选择的照片与来自o.photoid < f.photoid的匹配相同。第二个条件(f)仅将o 1 中的行与photoid中具有较小JOIN的行(即先前创建的)对。 将此替换为您自己的早期定义,以便按预期获得第一张照片。

因为第二个LEFT JOINf,它会将o 1 中的所有行添加到结果集中,包括那些没有的行o中的任何匹配,因为f中没有之前的的照片,而不是当前从NULL中选择的照片。对于这些行,使用了一整行o s而不是WHERE中缺少的行。

a子句从连接所产生的结果集中过滤仅具有f值的对(oNULLo.photoido;即没有&#34;其他照片&#34;在f中找到的同一个相册中的早于 ,而不是来自LEFT JOIN的某张照片。这些是您期望的每张专辑的第一张照片。

注释

1 a将已加入(左)的表fo与表INNER JOIN(右)组合在一起。结果集将包含由a ff生成的行的所有行组合,至少一次(而不是如上所述photoid的所有行;我更喜欢这样写它以使其更简单。)

2 我假设表TBLphotos中有一个名为PK的字段,它是表格的ON(它对于有明显的价值观)。如果您更改排序条件以从表中定义第一个照片(例如,使用上传时间),并且您使用的字段没有不同的值,那么在查询中返回所有具有的照片所选列的最小值相同。您可以通过在photoid子句中保留/添加使用SELECT(或其他可以解决关系的字段)的条件来轻松解决此问题。

3 您可以将您想要/需要的任何字段放入a子句中,但只能放在表fo中。没有什么可以阻止您放置NULL的字段,但所有字段都是WHERE。如果您不理解原因,请再次阅读完整的解释。

4 如果您想了解此查询的工作原理,请删除GROUP BY子句,使用MySQL客户端运行它并分析结果集。

5 您会在SO标记上找到类似问题的大量答案。如果他们使用GROUP BY来避免它们,因为它们是错误的并且不符合SQL标准(大多数都是偶然的)。如果他们使用子查询(在内部查询中有或没有{{1}}),他们可能是正确的,但大多数时候它们很慢。子查询很难优化,很多时候甚至都不可能。如果他们使用MySQL变量,那么他们也很慢。我不知道为什么MySQL变量很慢,我想这是因为在这种情况下查询规划器无法充分利用索引。