我可以连接两个表,其中联接表按某列排序吗?

时间:2010-05-23 07:43:11

标签: sql mysql inner-join

我不是一个数据库专家,所以我需要一些关于我正在处理的查询的帮助。在我的照片社区项目中,我希望通过不仅显示标签名称和计数器(其中的图像数量)来丰富地可视化标签,我还想在标签内显示最流行图像的拇指(大多数业力)。

表格设置如下:

  • 图像表保存基本图像元数据,重要的是业力字段
  • Imagefile表每个图像包含多个条目,每种格式一个
  • 标签表包含标签定义
  • Tag_map表将标签映射到图像

在我通常的试验和错误查询创作中,我走到了这一步:

SELECT * FROM

(SELECT tag.name, tag.id, COUNT(tag_map.tag_id) as cnt
FROM tag INNER JOIN tag_map ON (tag.id = tag_map.tag_id)
INNER JOIN image ON tag_map.image_id = image.id
INNER JOIN imagefile on image.id = imagefile.image_id 
WHERE imagefile.type = 'smallthumb'
GROUP BY tag.name
ORDER BY cnt DESC)

as T1 WHERE cnt > 0 ORDER BY cnt DESC

[为了简单起见,内部查询的列子句被剪断]

这个查询给了我一些我需要的东西。外部查询确保仅返回至少有1个图像的标记。内部查询返回标签详细信息,例如其名称,计数(图像数)和拇指。另外,我可以根据需要对内部查询进行排序(大多数图像,按字母顺序,最近等)

到目前为止一切顺利。然而问题是这个查询与标签中最流行的图像(大多数业力)不匹配,它似乎总是采用标签中最新的一个。

如何确保最受欢迎的图片与标签匹配?

2 个答案:

答案 0 :(得分:4)

您正在寻找'having'子句组,而不是嵌套选择!

SELECT tag.name, tag.id, COUNT(tag_map.tag_id) as cnt
  FROM tag 
 INNER JOIN tag_map 
    ON (tag.id = tag_map.tag_id)
 INNER JOIN image 
    ON tag_map.image_id = image.id
 INNER JOIN imagefile 
    on image.id = imagefile.image_id 
 WHERE imagefile.type = 'smallthumb'
 GROUP BY tag.name HAVING COUNT(tag_map.tag_id) > 0
 ORDER BY cnt DESC

答案 1 :(得分:3)

这应该非常接近:

SELECT
  tag.id, 
  tag.name,
  tag_group.cnt,
  tag_group.max_karma,
  image.id, 
  imagefile.filename
  /* ... */
FROM
  tag
  /* join against a list of max karma values (per tag) */
  INNER JOIN (
    SELECT   MAX(image.karma) AS max_karma, COUNT(image.*) cnt, tag_map.tag_id
    FROM     image
             INNER JOIN tag_map ON tag_map.image_id = image.id
    GROUP BY tag_map.tag_id
  ) AS tag_group ON tag_group.tag_id = tag.id
  /* join against a list of image ids (per max karma value and tag) */
  INNER JOIN (
    SELECT   MAX(image.id) id, tag_map.tag_id, image.karma
    FROM     image
             INNER JOIN tag_map ON tag_map.image_id = image.id
    GROUP BY tag_map.tag_id, image.karma /* collapse >1 imgs with same karma */
  ) AS pop_img ON pop_img.tag_id = tag.id AND pop_img.karma = tag_group.max_karma
  /* join against actual base data (per popular image id) */
  INNER JOIN 
    image ON image.id = pop_img.id
  INNER JOIN
    imagefile ON imagefile.image_id = pop_img.id AND imagefile.type = 'smallthumb'

基本上,这是the ever-recurring "max-per-group" problem:如何选择与组的最大/最小值相对应的记录?

一般答案总是如下:选择您的组(tag_id, MAX(image.karma)),然后根据这些特征加入您的基础数据。可能存在DBMS特定的专有扩展,采用不同的方法,例如使用ROW_NUMBER() / PARTITION BY。但是,这些不是非常便携,在使用不支持它们的DBMS时可能会让您感到头疼。