如何修改此SQL查询

时间:2012-04-16 05:59:03

标签: mysql sql

我的查询不完整,需要一些帮助。它目前使用低效的subselect运行,我很确定使用连接会使它更快。 此外,还有一个需要添加的查询元素,我不太清楚该怎么做。详细说明:

我有3张桌子

- album
 * albumId
 * albumName

- objectTag
 * objectTagObjectId (FK reference to albumId)
 * objectTabTagId (FK reference to tagId)

- tag
 * tagId
 * tagName

我要做的是根据链接到传递给查询的另一个相册的标签生成随机相册列表(假设为50)。

例如,我有一张名为“Britney Spears Greatest Hits”的专辑,该专辑标有“pop”和“cheese”。然后我将查询传递给该Britney专辑的id,并希望查询生成50个随机其他专辑的列表,这些专辑标有“pop”和“cheese”。

如果只有20张带有这些标签的相册,那么查询应该使用任意随机相册填充其他30条记录,而不管标签如何。

到目前为止,我可以根据标签获得随机相册:

SELECT albumId, albumName, objectTagTagId
FROM album
LEFT JOIN objectTag
  ON objectTagObjectId = albumId
WHERE objectTagTagId IN
(
  SELECT objectTagTagId
  FROM album
  LEFT JOIN objectTag
    ON objectTagObjectId = albumId
  WHERE albumId = 2471
)
ORDER BY RAND()
LIMIT 0,50

如上所述,这是低效且不完整的:

a)如何通过连接而不是子选择来提高效率?这可能吗?

b)如何修改此查询,以便如果只有x个与标记匹配的记录(假设为20),则余数用随机记录填充而不管标记是什么?

2 个答案:

答案 0 :(得分:1)

我不能保证效率,但这是一个想法...

SELECT * FROM (
  SELECT albumId, albumName, objectTagTagId FROM (
    (
    SELECT count(*) AS cnt, Out.albumId, Out.albumName, objectTagTagId
    FROM album Src
    JOIN objectTag sT
      ON (Src.ablumId = sT.objectTagObjectId)
    JOIN objectTag oT
      USING (objectTabTagId)
    JOIN album Out
    ON (Out.albumId = oT.objectTagObjectId)
    WHERE Src.albumId = 2471
        AND Out.albumId != 2471
    GROUP BY albumId, albumName, objectTagTagId
    )
    UNION     
    (
    SELECT 0 AS cnt, albumId, albumName, null AS objectTagTagId
    FROM album
    ORDER BY RAND()
    LIMIT 50
    )

  ) foo ORDER BY cnt DESC LIMIT 50
) goo ORDER BY RAND()

count(*)/ group by将计算专辑与src专辑共有的标签数量。

联盟将为我们提供50张填充专辑,其cnt为零,由ORDER BY和LIMIT命名为foo的底部。

goo上的ORDER BY RAND()将随机化订单

答案 1 :(得分:0)

如果没有嵌套并且仅通过简单连接,您就无法编写预期的查询,因为您需要将相册2471的所有标签都存在于您想要返回的相册中。当然,您可以通过EXISTS-nesting等替换IN-nesting。