sql - 连接查询是否正确?

标签 sql mysql join

我有多个表,我想加入这些表以获得特定结果。

表格是:

ad_categories, ad_image, ad_data, ad_location

我需要为 ad_categories 表中的以下每一行输出一行,无论在使用 WHERE 条件时是否存在特定位置的任何这些类别的数据。

mysql> SELECT type FROM ad_categories;
+---------------+
| type          |
+---------------+
| restaurants   |
| fitness       |
| funactivities |
| shopping      |
| homes         |
| men           |
+---------------+

例如:

mysql> SELECT alias, type, sha, originalname FROM ad_categories LEFT JOIN ad_data ON ad_data.cid=ad_categories.id LEFT JOIN ad_image ON ad_image.pid=ad_data.id LEFT JOIN ad_location ON ad_location.id=ad_data.lid GROUP BY type;
+--------+---------------+------------------------------------------+---------------------------------+
| alias  | type          | sha                                      | originalname                    |
+--------+---------------+------------------------------------------+---------------------------------+
| malibu | fitness       | ad8b277202f4ded274274744b3fa28f34e9f1c21 | thai_body_works.jpg             |
| malibu | funactivities | 6a226df8ff827aa020b077e9e0d48e4701ae2fca | rosenthal-the_malibu_estate.jpg |
| NULL   | homes         | NULL                                     | NULL                            |
| NULL   | men           | NULL                                     | NULL                            |
| malibu | restaurants   | 98f357dfa5bdb2eb1d480dc0e8b7156b1eecac31 | moonshadows.jpg                 |
| malibu | shopping      | 1b2ef538691569842b9f9fb6c3816673f334205a | malibu_surf_shack.jpg           |
+--------+---------------+------------------------------------------+---------------------------------+
6 rows in set (0.00 sec)

列出了我需要的所有类别类型,但我没有指定我需要做的位置。我只想要每种类型、每个指定位置的一行。如果该位置的类别类型不存在数据,请为类型以外的列填写空值。

mysql> SELECT alias, type, sha, originalname FROM ad_categories LEFT JOIN ad_data ON ad_data.cid=ad_categories.id JOIN ad_image ON ad_image.pid=ad_data.id LEFT JOIN ad_location ON ad_location.id=ad_data.lid WHERE ad_location.alias='malibu' GROUP BY type;
+--------+---------------+------------------------------------------+---------------------------------+
| alias  | type          | sha                                      | originalname                    |
+--------+---------------+------------------------------------------+---------------------------------+
| malibu | fitness       | ad8b277202f4ded274274744b3fa28f34e9f1c21 | thai_body_works.jpg             |
| malibu | funactivities | 6a226df8ff827aa020b077e9e0d48e4701ae2fca | rosenthal-the_malibu_estate.jpg |
| malibu | restaurants   | 98f357dfa5bdb2eb1d480dc0e8b7156b1eecac31 | moonshadows.jpg                 |
| malibu | shopping      | 1b2ef538691569842b9f9fb6c3816673f334205a | malibu_surf_shack.jpg           |
+--------+---------------+------------------------------------------+---------------------------------+
4 rows in set (0.00 sec)

我不是专业的 SQL 忍者。如果我错误地构建了 SQL 查询,有人可以纠正我,或者可以通过一些线索来指导我如何正确完成我想做的事情吗?谢谢。

最佳答案

使用:

SELECT alias, type, sha, originalname
  FROM (SELECT alias, 
               type, 
               sha, 
               originalname,
               CASE WHEN @type = type THEN @rownum := @rownum + 1 ELSE @rownum := 1 END AS rank,
               @type := type
          FROM AD_CATEGORIES c 
     LEFT JOIN AD_DATA d ON d.cid = c.id 
     LEFT JOIN AD_LOCATION l ON l.id = d.lid 
                            AND l.alias = ?
     LEFT JOIN AD_IMAGE i ON i.pid = d.id 
          JOIN (SELECT @rownum := 0, @type := '') r
      ORDER BY type, l.id DESC) x
 WHERE x.rank = 1

我唯一没有的是我假设 AD_LOCATION 中的哪一列,您将指定“malibu”/etc 作为位置。 ORDER BY 很重要,以确保非 NULL 别名/位置排在 NULL 之前...

分割

这个:

JOIN (SELECT @rownum := 0, @type := '') r

...允许您定义和初始化变量,而无需使用单独的 SET 命令。

这些:

CASE
   WHEN @type = type THEN @rownum := @rownum + 1  -- increments rownum when type matches
   ELSE @rownum := 1 -- resets rownum to 1 when @type != type
END AS rank,
@type := type -- need this to set @type for the next rows comparison

请查看“--”之后的内容以进行逐行注释。

ORDER BY type, l.id DESC

必须使用 ORDER BY 来保持类型值的顺序,否则排名值将不会如我们所愿。 ORDER BY 的第二部分确保非 NULL 的位置值首先出现,如果有任何基于过滤的话。

最后,外部查询只得到rank值为1的行...

关于sql - 连接查询是否正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3535420/

相关文章:

mysql - 我需要使用 LENGTH 函数从 2 个不同的表中提取值,但仅使用 1 个查询

mysql - 注释表 mySQL

php - 协助 MySQL 左外连接并区分同一键的查询结果

sql - 基于子字符串连接2个sql表

sql - 在任何 OUTER JOIN 之后使用 INNER JOIN 是否真的会使 OUTER JOIN 的效果无效?

mysql - 不能在 mysql 函数中使用别名作为 ORDER BY 子句的一部分

sql - Sequelize findAll 多对多条件

php - 如何对数据库表中的数据进行随机排序并将结果插入到其他表中

php - 列出对数据库的所有查询

php - mysql_insert_id() 查看最后插入记录的值