SQL - 避免笛卡尔积

时间:2014-02-04 15:37:16

标签: sql database cartesian-product

我需要从3个表中编写一个SQL语句,一个列出Web URL的表,一个列出可能类别的表,然后是一个名为URL_Categories的表。 (类似于经典的学生/课程/注册SQL问题)。 URL和CATEGORY的组合使URL_CATEGORIES成为可能。一个URL可能具有1个或“X”类别,因此URL_CATEGORY表中可以有多个行,但URL和CATEGORY的COMBINATION在URL_CATEGORY表中是唯一的。适用的CREATE TABLE定义是:

CREATE TABLE URL (
  ID AUTOINC,
  SOURCE_DATE DATETIME,
  SITE VARCHAR(30),
 ...
); -186 rows


CREATE TABLE CATEGORY (
  ID AUTOINC,
  CATEGORY_NAME VARCHAR(20),   
);  -- 9 rows

CREATE TABLE URL_CATEGORIES (
  URL_ID INTEGER,
  CAT_ID INTEGER,  
); - 195 rows

简而言之,我希望看到所有专栏。由于URL_CATEGORIES有195行,因此我的OUTPUT应该有195行。对于URL_CATEGORIES表中的每一行,选择URL表中URL_CATEGORIES.URL_ID = URL.ID的所有相应列以及CATEGORY表中URL_CATEGORIES.CAT_ID = CATEGORY.ID的所有列。

我正在使用的SQL给了我38025行,告诉我我有一个笛卡尔问题...... SQL是

select U1."*", C2."*", U3."*"
  from "URL_CATEGORIES" U1 
 inner join "CATEGORY" C2
    on (U1."CAT_ID" = C2."ID"),
      "URL_CATEGORIES" U1 
 inner join "URL" U3
    on (U1."URL_ID" = U3."ID")

我在想我需要一个子选择来获取第3个表上的行,而不是连接。我如何重写SQL?

由于

1 个答案:

答案 0 :(得分:2)

您在from声明中有逗号,并再次引用url_categories,因此您将获得笛卡尔积。查询将其解释为cross join。试试这个:

select U1.*, C2.*, U3.*
from URL_CATEGORIES U1 inner join
      CATEGORY C2
      on U1.CAT_ID = C2.ID inner join
      URL U3
      on U1.URL_ID = U3.ID

此查询不需要双引号。