【问题标题】:MYSQL JOIN with unique result rows具有唯一结果行的 MYSQL JOIN
【发布时间】:2011-04-19 08:01:27
【问题描述】:

假设我有 2 个表,一个称为类别,一个称为 cat_pages。

类别表具有列 ID、标题和时间戳。例如:

CREATE TABLE categories (
    id INT UNSIGNED PRIMARY KEY,
    title VARCHAR(32),
    `timestamp` TIMESTAMP,
    INDEX (title)
) Engine=InnoDB;

cat_pages 有 2 列,cat_id 和 page_id:

CREATE TABLE cat_pages (
    cat_id INT UNSIGNED 
        REFERENCES categories (id) 
        ON DELETE CASCADE ON UPDATE CASCADE,
    page_id INT UNSIGNED
        REFERENCES pages (id) 
        ON DELETE CASCADE ON UPDATE CASCADE,
    UNIQUE INDEX (cat_id, page_id),
    INDEX (page_id, cat_id),
) Engine=InnoDB;

我正在尝试将类别表与 ID 上的 cat_pages 表连接起来,这样

  1. 仅检索在 category_pages 表中具有 id 的类别并
  2. 每个类别在结果集中只显示一次

查询:

SELECT * FROM categories as c
    LEFT JOIN cat_pages as p ON c.id = p.cat_id

生成一个类别重复多次的结果集(因为 cat_pages 表中有多个匹配项。我需要什么才能使每个类别仅显示一次,如果 cat_pages 中没有匹配项则根本不显示桌子?

【问题讨论】:

  • 从查询中删除 LEFT 以达到第一点
  • 代码为王。描述表的最佳方式是给出表创建语句,以及用于示例数据的INSERT 语句。您提供的 SELECT 查询非常有助于描述您想要什么。

标签: mysql sql join


【解决方案1】:

为什么不使用内部联接?

SELECT * FROM categories as c INNER JOIN cat_pages as p ON c.id = p.cat_id

或者

SELECT * FROM categories as c LEFT JOIN cat_pages as p ON c.id = p.cat_id WHERE p.cat_id IS NOT NULL

Left Join 选择左表上的所有内容和右表上的匹配项。

【讨论】:

    【解决方案2】:

    如果您不想要不在cat_pages 中的类别,请不要使用左连接;使用内部连接。左连接包括左表中的每一行,即使右表中没有匹配的行(缺失的字段被赋予 NULL 值)。右连接类似,但包括右表中的所有行。外连接包括左表和右表中的所有行,连接有匹配的行和连接没有匹配的行与 NULL 值。相比之下,内连接只包括匹配的行。换句话说,左右连接的交集是内连接;他们的联合是外连接。 Jeff Atwood 发布了一些不错的 Venn diagrams describing joins,不过需要注意的是,圆圈中的集合并不是正确的左右表,而是左右表的左右连接的结果。

    要获得不同的行,您可以使用DISTINCT 修饰符:

    SELECT DISTINCT c.* 
      FROM categories AS c 
        INNER JOIN cat_pages AS cp ON c.id = cp.cat_id
    

    至于SELECT * ...,见“What is the reason not to use select *?

    获得不同行的另一种方法是使用EXISTS 子句或IN 运算符,但连接可能更高效(尽管只有EXPLAIN 可以肯定地告诉您)。只需确保设置了适当的索引即可。

    【讨论】:

    • 很好的答案,DISTINCT 正是我正在寻找的......我不知道为什么我没有进行内部连接。也感谢您对 select * 的提醒。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 2016-10-07
    • 2017-05-12
    • 2013-10-07
    • 2013-02-04
    • 2014-11-04
    相关资源
    最近更新 更多