您好我想创建一个我想要相册的网站。
事情是这个网站将有2个表,1个表存储相册的名称(TBLalbum
)和该相册的唯一ID(id
,albumname
)。
第二个表格(TBLphotos
)存储有关已上传照片的信息以及每张照片所属的相册(albumid
,photoname
以及更多列)。
现在我想列出所有不太难做的专辑名称,但是在相同的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
。
我有点难以解释,但有谁能告诉我如何解决这个问题?
答案 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
别名为a
与TBLphotos
(别名为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 JOIN
是f
,它会将o
1 中的所有行添加到结果集中,包括那些没有的行o
中的任何匹配,因为f
中没有之前的的照片,而不是当前从NULL
中选择的照片。对于这些行,使用了一整行o
s而不是WHERE
中缺少的行。
a
子句从连接所产生的结果集中过滤仅具有f
值的对(o
,NULL
,o.photoid
) o
;即没有&#34;其他照片&#34;在f
中找到的同一个相册中的早于 ,而不是来自LEFT JOIN
的某张照片。这些是您期望的每张专辑的第一张照片。
1 a
将已加入(左)的表f
和o
与表INNER JOIN
(右)组合在一起。结果集将包含由a
f
和f
生成的行的所有行组合,至少一次(而不是如上所述photoid
的所有行;我更喜欢这样写它以使其更简单。)
2 我假设表TBLphotos
中有一个名为PK
的字段,它是表格的ON
(它对于有明显的价值观)。如果您更改排序条件以从表中定义第一个照片(例如,使用上传时间),并且您使用的字段没有不同的值,那么在查询中返回所有具有的照片所选列的最小值相同。您可以通过在photoid
子句中保留/添加使用SELECT
(或其他可以解决关系的字段)的条件来轻松解决此问题。
3 您可以将您想要/需要的任何字段放入a
子句中,但只能放在表f
和o
中。没有什么可以阻止您放置NULL
的字段,但所有字段都是WHERE
。如果您不理解原因,请再次阅读完整的解释。
4 如果您想了解此查询的工作原理,请删除GROUP BY
子句,使用MySQL客户端运行它并分析结果集。
5 您会在SO标记greatest-n-per-group上找到类似问题的大量答案。如果他们使用GROUP BY
来避免它们,因为它们是错误的并且不符合SQL标准(大多数都是偶然的)。如果他们使用子查询(在内部查询中有或没有{{1}}),他们可能是正确的,但大多数时候它们很慢。子查询很难优化,很多时候甚至都不可能。如果他们使用MySQL变量,那么他们也很慢。我不知道为什么MySQL变量很慢,我想这是因为在这种情况下查询规划器无法充分利用索引。