连接查询是否正确?

时间:2010-08-20 22:56:44

标签: 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查询或者教我一些关于如何正确完成我想做的事情的线索,有人可以纠正我吗?感谢。

3 个答案:

答案 0 :(得分:2)

使用:

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的位置值,如果有任何基于过滤的话。

最后,外部查询只获取等级值为1 ...

的行

答案 1 :(得分:0)

您需要使用“外部联接”。

答案 2 :(得分:0)

独自留下一段时间,回到它身边。这是我需要的答案,感谢一位同事在新工作:

SELECT 
    alias, type, sha, originalname 
FROM 
    ad_categories 
LEFT JOIN 
    ad_location ON ad_location.alias = '?' 
LEFT JOIN 
    ad_data ON ad_data.cid=ad_categories.id AND ad_location.id=ad_data.lid 
LEFT JOIN 
    ad_image ON ad_image.pid=ad_data.id GROUP BY type;

感谢同事;)