0

我有一个不完整的查询,需要一些帮助。它目前使用效率低下的子选择运行,我很确定使用连接会使其稍后更快。此外,查询中有一个元素需要添加,我不太确定该怎么做。细节:

我有 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 条),则其余部分填充随机记录而与标签无关?

4

2 回答 2

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() 将使订单随机化

于 2012-04-16T06:29:51.267 回答
0

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

于 2012-04-16T06:28:53.690 回答