0

我在一个表(A)中有一个东西,在另外两个(C1,C2)category_id 来自不同的表(MC)。

我想计算在特定类别中展示了多少东西。

实时数据示例:

表A

main_key (unique)    stuff_id (non unique)
   1                    7
   2                    6 
   3                    3

表C1

category_id main_key (it is FK for A table)
   1             1
   1             2
   3             1

表C2

category_id main_key (it is FK for A table)
   2             3
   2             1

表 MC

category_id category_name
   1             blablbl
   2               asas
   3             asasa
...

之间的关系: C1 和 A 多对一 C2 和 A 多对一 C1 或 C2 和 MC 多对一

在当前示例中,我希望看到最终结果为

stuff_qnt        category_id        category_name
2                   1                  blablbl
2                   2                   asas
1                   3                   asasa

我如何通过一个查询来实现它?

我的查询是:

SELECT count(A.stuff_id) as stuff_qnt, MC.category_id, MC.category_name 
FROM A
LEFT JOIN C1 using(main_key)
LEFT JOIN C2 using(main_key)
LEFT JOIN MC ON (C1.category_id = MC.category_id AND C2.category_id = MC.category_id)
GROUP BY C1.category_id, C2.category_id

但它向我显示了错误的结果,我做错了什么?

4

3 回答 3

1
SELECT COUNT(*) AS Stuff_Qnt, C.Category_ID, MC.Category_Name
  FROM MC
  JOIN (SELECT C1.Category_ID
          FROM A
          JOIN C1 ON A.Main_Key = C1.Main_Key
        UNION ALL
        SELECT C2.Category_ID
          FROM A
          JOIN C2 ON A.Main_Key = C2.Main_Key
       ) AS C
    ON C.Category_ID = MC.Category_ID
 GROUP BY C.Category_ID, MC.Category_Name
 ORDER BY C.Category_ID, Stuff_Qnt;

您需要将 A 与 C1 连接的类别以及将 A 与 C2 连接的类别,并且您绝对不想要使用 LEFT OUTER JOIN 获得的笛卡尔积,因此您采用类别 ID 列表的 UNION ,然后与 MC 聚合并加入。

CREATE TABLE A
(
    main_key INTEGER NOT NULL PRIMARY KEY,
    stuff_id INTEGER NOT NULL
);
INSERT INTO A VALUES(1, 7);
INSERT INTO A VALUES(2, 6);
INSERT INTO A VALUES(3, 3);

CREATE TABLE MC
(
    category_id INTEGER NOT NULL PRIMARY KEY,
    category_name VARCHAR(10) NOT NULL
);
INSERT INTO mc VALUES(1, "blablbl");
INSERT INTO mc VALUES(2, "asas");
INSERT INTO mc VALUES(3, "asasa");

CREATE TABLE C1
(
    category_id INTEGER NOT NULL REFERENCES mc,
    main_key INTEGER NOT NULL REFERENCES a
);
INSERT INTO c1 VALUES(1, 1);
INSERT INTO c1 VALUES(1, 2);
INSERT INTO c1 VALUES(3, 1);

CREATE TABLE C2
(
    category_id INTEGER NOT NULL REFERENCES mc,
    main_key INTEGER NOT NULL REFERENCES a
);
INSERT INTO c2 VALUES(2, 3);
INSERT INTO c2 VALUES(2, 1);

SELECT COUNT(*) AS Stuff_Qnt, C.Category_ID, MC.Category_Name
  FROM MC
  JOIN (SELECT C1.Category_ID
          FROM A
          JOIN C1 ON A.Main_Key = C1.Main_Key
        UNION ALL
        SELECT C2.Category_ID
          FROM A
          JOIN C2 ON A.Main_Key = C2.Main_Key
       ) AS C
    ON C.Category_ID = MC.Category_ID
 GROUP BY C.Category_ID, MC.Category_Name
 ORDER BY C.Category_ID, Stuff_Qnt;

输出:

2   1   blablbl
2   2   asas
1   3   asasa

这是进一步的测试,A 中有两行额外的行,C1 和 C2 中有相应的行。测试了两个查询,我的查询dkkumargoyal的查询。

CREATE TABLE A(main_key INTEGER NOT NULL PRIMARY KEY, stuff_id INTEGER NOT NULL);
INSERT INTO A VALUES(1, 7);
INSERT INTO A VALUES(2, 6);
INSERT INTO A VALUES(3, 3);
INSERT INTO A VALUES(4, 3);
INSERT INTO A VALUES(5, 3);

CREATE TABLE MC(category_id INTEGER NOT NULL PRIMARY KEY, category_name VARCHAR(10) NOT NULL);
INSERT INTO mc VALUES(1, "blablbl");
INSERT INTO mc VALUES(2, "asas");
INSERT INTO mc VALUES(3, "asasa");

CREATE TABLE C1(category_id INTEGER NOT NULL REFERENCES mc, main_key INTEGER NOT NULL REFERENCES a);
INSERT INTO c1 VALUES(1, 1);
INSERT INTO c1 VALUES(1, 2);
INSERT INTO c1 VALUES(3, 1);
INSERT INTO c1 VALUES(3, 4);
INSERT INTO c1 VALUES(1, 4);
INSERT INTO c1 VALUES(1, 5);

CREATE TABLE C2(category_id INTEGER NOT NULL REFERENCES mc, main_key INTEGER NOT NULL REFERENCES a);

INSERT INTO c2 VALUES(2, 3);
INSERT INTO c2 VALUES(2, 1);
INSERT INTO c2 VALUES(2, 5);

SELECT COUNT(*) AS Stuff_Qnt, C.Category_ID, MC.Category_Name
  FROM MC
  JOIN (SELECT C1.Category_ID
          FROM A
          JOIN C1 ON A.Main_Key = C1.Main_Key
        UNION ALL
        SELECT C2.Category_ID
          FROM A
          JOIN C2 ON A.Main_Key = C2.Main_Key
       ) AS C
    ON C.Category_ID = MC.Category_ID
 GROUP BY C.Category_ID, MC.Category_Name
 ORDER BY C.Category_ID, Stuff_Qnt;

-- Query by dkkumargoyal
SELECT COUNT(DISTINCT A.stuff_id) AS stuff_qnt, MC.category_id, MC.category_name 
FROM A
LEFT JOIN C1 on a.main_key = c1.main_key  -- USING(main_key)
LEFT JOIN C2 on a.main_key = c2.main_key  -- USING(main_key)
LEFT JOIN MC ON (C1.category_id = MC.category_id OR C2.category_id = MC.category_id)
GROUP BY MC.category_id, mc.category_name
ORDER BY MC.Category_id, stuff_qnt;       -- stuff_qnt added for standard compatibility

所做的更改对于代码在测试 DBMS (Informix 11.70.FC6) 上工作是必要的。

结果1:

4   1   blablbl
3   2   asas
2   3   asasa

结果 2:

3   1   blablbl
2   2   asas
2   3   asasa

A.Stuff_ID我认为我的结果是正确的,另一个不是,主要是因为当问题规定它不是唯一的(并且额外的数据行使其不唯一)时,替代方案取决于唯一性。

于 2012-12-12T13:03:47.343 回答
1

请看一下这个参考:

询问:

select m.category_id, m.category_name, count(a.stuff_id) as cntstuff from
(select * from c1 
 union all
 select * from c2) as c
join a 
on a.main_key = c.main_key
join mc m
on m.category_id = c.category_id
group by m.category_id
order by m.category_id
;

结果:

CATEGORY_ID     CATEGORY_NAME   CNTSTUFF
1               blablbl         2
2               asas            2
3               asasa           1
于 2012-12-12T13:41:09.820 回答
0

试试这个 SQL。

SELECT COUNT(DISTINCT A.stuff_id) AS stuff_qnt, MC.category_id, MC.category_name 
FROM A
LEFT JOIN C1 USING(main_key)
LEFT JOIN C2 USING(main_key)
LEFT JOIN MC ON (C1.category_id = MC.category_id OR C2.category_id = MC.category_id)
GROUP BY MC.category_id
于 2012-12-12T13:18:08.087 回答