需要一些有关 MySQL 子查询计数的帮助

发布于 2024-08-25 13:40:48 字数 757 浏览 3 评论 0原文

我遇到了自己的 MySQL 查询技能限制,所以我希望一些 SQL 专家可以在这方面提供帮助。情况如下:

我有可以标记的图像。正如您所期望的,它存储在三个表中:

  • 图像
  • 标签
  • Tag_map(将图像映射到标签)

我有一个 SQL 查询,它根据标签 ID 计算相关标签。该查询基本上检查使用该标签的图像用于图像的其他标签。示例:

Image1 标记为“熊”
Image2 标记为“Bear”和“Canada”

如果我在查询中抛出“Bear”(或其标签 ID),它将返回“Canada”。这很好用。这是查询:

SELECT tag.name, tag.id, COUNT(tag_map.id) as cnt
FROM tag_map,tag
WHERE tag_map.tag_id = tag.id AND tag.id != '185' AND tag_map.image_id IN

    (SELECT tag_map.image_id FROM tag_map INNER JOIN tag ON tag_map.tag_id = tag.id WHERE tag.id = '185')

GROUP BY tag_map.id LIMIT 0,100

我所困惑的部分是计数。对于返回的每个相关标签,我想知道该标签中有多少图像。目前它总是返回 1,即使有例如 3。我尝试过计算不同的列,所有列都会产生相同的输出,所以我猜我的想法有缺陷。

I'm running into my own limits of MySQL query skills, so I hope some SQL guru can help out on this one. The situation is as follow:

I have images that can be tagged. As you might expect this is stored in three tables:

  • Image
  • Tag
  • Tag_map (maps images to tags)

I have a SQL query that calculates the related tags based on a tag id. The query basically checks what other tags were used for images for images using that tag. Example:

Image1 tagged as "Bear"
Image2 tagged as "Bear" and "Canada"

If I throw "Bear" (or its tag id) at the query, it will return "Canada". This works fine. Here's the query:

SELECT tag.name, tag.id, COUNT(tag_map.id) as cnt
FROM tag_map,tag
WHERE tag_map.tag_id = tag.id AND tag.id != '185' AND tag_map.image_id IN

    (SELECT tag_map.image_id FROM tag_map INNER JOIN tag ON tag_map.tag_id = tag.id WHERE tag.id = '185')

GROUP BY tag_map.id LIMIT 0,100

The part I'm stuck with is the count. For each related tag returned, I want to know how many images are in that tag. Currently it always returns 1, even if there are for example 3. I've tried counting different columns all resulting in the same output, so I guess there is a flaw in my thinking.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白芷 2024-09-01 13:40:48

您的代码无法正常工作,因为您仅选择“与所选标签关联”的图像,而不是“与与所选标签关联的图像关联的标签关联”的图像(我希望,我使用了正确的递归深度:))。

您可以使用子选择来做到这一点:

SELECT tag.id, tag.name, COUNT(DISTINCT tag_map.image_id) as cnt
  FROM tag_map, tag
 WHERE tag_map.tag_id = tag.id
   AND tag.id != 185
   AND tag_map.tag_id IN (
     SELECT sub1.tag_id FROM tag_map AS sub1 WHERE sub1.image_id IN (
       SELECT sub2.image_id FROM tag_map AS sub2 WHERE sub2.tag_id = 185
     )
   )
GROUP BY tag.id, tag.name;

Your code not working right because you select just images "associated with a choosen tag", but not images, "associated with tags associated with image associated with choosen tag" (I hope, I used correct recursion depth :) ).

You can do this with subselects:

SELECT tag.id, tag.name, COUNT(DISTINCT tag_map.image_id) as cnt
  FROM tag_map, tag
 WHERE tag_map.tag_id = tag.id
   AND tag.id != 185
   AND tag_map.tag_id IN (
     SELECT sub1.tag_id FROM tag_map AS sub1 WHERE sub1.image_id IN (
       SELECT sub2.image_id FROM tag_map AS sub2 WHERE sub2.tag_id = 185
     )
   )
GROUP BY tag.id, tag.name;
神也荒唐 2024-09-01 13:40:48

一些深思熟虑

  • 我注意到您在标签中使用了id tag_map 表中的 image 表和 tablename_id 。每个人都有自己的路线,但我发现如果每个地方的 id 命名都相同,那就容易多了。我会重命名 tag & 中的 id图像到 tag_id & image_id 分别。
  • 看来你的 id 是字符串。我在示例中冒昧地使用了整数。

以下示例使用 SQL Server。将SQL语句调整到MySQL应该不会太难。

测试数据

DECLARE @tag TABLE (id INTEGER, tag VARCHAR(32))
DECLARE @image TABLE (id INTEGER, image VARCHAR(32))
DECLARE @tag_map TABLE (image_id INTEGER, tag_id INTEGER)

INSERT INTO @tag
SELECT 185, 'Bear' 
UNION ALL SELECT 186, 'Canada'

INSERT INTO @image
SELECT 1, 'image1'
UNION ALL SELECT 2, 'image2'

INSERT INTO @tag_map
SELECT 1, 185
UNION ALL SELECT 2, 185
UNION ALL SELECT 2, 186

SQL语句

SELECT  t.tag
        , t.id
        , cnt = (SELECT COUNT(*) FROM @tag_map WHERE tag_id = t.id)
FROM    @tag_map m
        INNER JOIN @tag t ON t.id = m.tag_id
        INNER JOIN (
          SELECT  m.image_id
          FROM    @tag_map m
          WHERE   m.tag_id = 185
        ) i ON i.image_id = m.image_id
WHERE   t.id <> 185

Some food for thought

  • I noticed you use id in your tag & image table and tablename_id in your tag_map table. Each his own offcourse, but I found it to be much easier if an id is named the same everywhere. I would rename the id's in tag & image to tag_id & image_id respectively.
  • It seems your id's are character strings. I've taken the liberty to use integers in the examples.

The following example uses SQL Server. It should not be to hard to adjust the SQL Statement to MySQL.

Test data

DECLARE @tag TABLE (id INTEGER, tag VARCHAR(32))
DECLARE @image TABLE (id INTEGER, image VARCHAR(32))
DECLARE @tag_map TABLE (image_id INTEGER, tag_id INTEGER)

INSERT INTO @tag
SELECT 185, 'Bear' 
UNION ALL SELECT 186, 'Canada'

INSERT INTO @image
SELECT 1, 'image1'
UNION ALL SELECT 2, 'image2'

INSERT INTO @tag_map
SELECT 1, 185
UNION ALL SELECT 2, 185
UNION ALL SELECT 2, 186

SQL Statement

SELECT  t.tag
        , t.id
        , cnt = (SELECT COUNT(*) FROM @tag_map WHERE tag_id = t.id)
FROM    @tag_map m
        INNER JOIN @tag t ON t.id = m.tag_id
        INNER JOIN (
          SELECT  m.image_id
          FROM    @tag_map m
          WHERE   m.tag_id = 185
        ) i ON i.image_id = m.image_id
WHERE   t.id <> 185
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文