【问题标题】:MySQL Query with some type of join? Not sureMySQL Query 与某种类型的连接?没有把握
【发布时间】:2009-09-01 05:04:50
【问题描述】:

如果有人能推荐一本学习mySQL的好书,那就太好了:)。

我有两个表,tagscodes_tags

CREATE TABLE `tags` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(40) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=190 DEFAULT CHARSET=utf8


CREATE TABLE `codes_tags` (
 `code_id` int(11) unsigned NOT NULL,
 `tag_id` int(11) unsigned NOT NULL,
 KEY `sourcecode_id` (`code_id`),
 KEY `tag_id` (`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

我要做的是从“tags”中选择名称,以及“codes_tags”中有多少个 tag_id,并按该数量排序。如果code_tags中没有该tag_id的记录,'count'应该等于0或NULL(最好是0)。

这是我迄今为止最接近的一次:

SELECT tags.name, COUNT( codes_tags.tag_id ) AS count
FROM tags
LEFT JOIN codes_tags ON tags.id = codes_tags.tag_id
GROUP BY tag_id
ORDER BY count DESC
LIMIT 0 , 30

它似乎做了我想要的,但是当它应该返回 30 时它只返回四行。

我在这里做错了什么? 谢谢。

【问题讨论】:

    标签: mysql select left-join


    【解决方案1】:

    我已经用一些虚拟数据在 MySQL 上对此进行了测试,查询似乎为我返回了超过 4 行。我运行了您的创建表语句,然后用以下语句填充它们:

    insert into tags (name) values ('java'), ('mysql'), ('php'), ('ruby'), ('.net'), ('python');
    insert into codes_tags (code_id, tag_id) values (1,194), (2,194), (3,194), (1,191), (2,191), (3,191), (4,191), (5,191), (1,192), (1,195), (1,193);
    

    当我对该数据运行查询时,它会返回 6 行。为了帮助进一步调试,您能否发布以下 2 个查询的结果:

    select count(*) from tags;
    select * from tags limit 10;

    另外,为了确保你有适当的数据完整性,你可以添加如下外键,看看是否成功?

    alter table codes_tags add foreign key codes_tags_tag_id_key(tag_id) references tags(id);

    【讨论】:

      【解决方案2】:

      我认为,如果您在 SELECT 中将 COUNT(codes_tags.tag_id) 更改为 COUNT(*),也会包含 NULL。 (如果您缺少空值或 0 个计数。否则,查询看起来很好)。

      编辑:再想一想,我错过了 LEFT JOIN。这意味着您需要所有标签,即使它们与 codes_tags 表中的某些内容无关。那是你要的吗?

      我可能会做以下事情:

      SELECT tags.name, COUNT(*) AS count
      FROM tags
      INNER JOIN codes_tags ON tags.id = codes_tags.tag_id
      GROUP BY tags.id
      ORDER BY count(*) DESC
      

      可以从列表中的not项推断出哪些标签也不包含在codes_tags中。但是,如果您也想明确地这样做:

      SELECT tags.name, COUNT(*) AS count
      FROM tags
      INNER JOIN codes_tags ON tags.id = codes_tags.tag_id
      GROUP BY tags.id
      UNION
      SELECT tags.name, '0'
      from tags
      where tags.name not in 
         (SELECT tags.name
         FROM tags
         INNER JOIN codes_tags ON tags.id = codes_tags.tag_id)
      ORDER BY count(*) DESC
      

      (我目前无法访问 SQL 框,因此请谨慎对待查询;它们未经测试。)

      【讨论】:

      • 对不起,我已经试过了。它返回的有点奇怪,第一条记录的计数是 185,然后它后面有 3 条,正确的计数是 1。但它仍然只返回 4 行。
      • 您的第二个 SQL 查询正是我所追求的。你能解释一下它的作用吗?
      • 第一个 SELECT 获取 tag 和 codes_tags 表中存在的所有这些名称的名称和计数。 UNION 说我想添加更多行(请注意,两个查询中的列类型和计数必须相同)。第二个 SELECT 获取名称和一个零(表示计数),但仅适用于第一个 SELECT 中的那些 NOT 项。 WHERE 子句将结果限制为未包含在第一个查询中的名称。
      【解决方案3】:

      LEFT JOIN 更改为LEFT OUTER JOIN

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-26
        • 2014-02-16
        • 1970-01-01
        • 2013-02-28
        • 1970-01-01
        • 1970-01-01
        • 2021-10-25
        相关资源
        最近更新 更多