从一列中选择在关联列中只有一个值的所有元素

时间:2017-09-11 21:10:17

标签: sql postgresql

我有以下数据库

Table A
id_a   
1
2
3
4

Table B
id_b  id_o   
1     2
2     2
3     2
4     5
5     8
6     2
7     5
8     1


Table C
id_a    id_b
1       3
1       2
3       6
2       8
4       4
4       7

我想从A中获取只有一个id_o来自表B的所有元素,其中表C是两个表之间的链接。所以在这种情况下它只会带给我

id_a  id_o
4     5

由于id_a = 4仅具有表B中与id_o = 5

相关联的记录

我想做的是:

SELECT
  c.id_a, b.id_o
FROM
  TableC c
JOIN
  TableB b
ON
  c.id_b = b.id_b
GROUP BY
  c.id_a, b.id_o
HAVING
  COUNT(id_o) = 1;

但这并不能归还我想要的东西,我做错了什么?

3 个答案:

答案 0 :(得分:1)

SQL语句

SELECT 
    ta.id_a,
    tb.id_o
FROM TableA AS ta
LEFT JOIN TableC AS tc ON tc.id_a = ta.id_a
LEFT JOIN TableB AS tb ON tb.id_b = tc.id_b
GROUP BY 
    ta.id_a,
    tb.id_o
HAVING COUNT(tb.id_o) = 1;

SQL语句的描述:

  • 选择TableA
  • 的所有记录
  • 附加,例如加入TableC(链接表)
  • 中的所有相应详细信息
  • 附加,例如加入TableB
  • 中的所有相应详细信息
  • TableA' id_aTableB' s id_o分组。
  • 计算每个组id_o的数量,并通过仅允许id_o s的数量等于1来过滤结果。

结果:

id_a    id_o
------------
2       1
3       2

注意:

  • 我还添加了TableA条记录(id_a = 5),没有任何相应的id_bid_o
  • 除了TableA详细信息之外,您甚至可以获取TableB详细信息(甚至是TableC详细信息),因为过滤后的分组记录代表了各个TableA条记录。条件是每个获取列上的GROUP。在其他情况下(例如,当您使用HAVING COUNT(tb.id_o) >= 1时)在TableB详细信息旁边获取TableC(或TableA)详细信息是不对的,因为结果无法正确显示。
  • 我还要提一下,如果您已经说过" TableC选择所有记录...... ",那么我会用SELECT ... FROM TableC AS tc LEFT JOIN ...开始我的sql语句,符合LEFT JOIN的定义:从LEFT表中将始终无条件地获取所有记录。之后可以应用过滤器。

使用的表结构

DROP TABLE IF EXISTS `TableA`;
CREATE TABLE `TableA` (
  `id_a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `TableB`;
CREATE TABLE `TableB` (
  `id_b` int(11) DEFAULT NULL,
  `id_o` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `TableC`;
CREATE TABLE `TableC` (
  `id_a` int(11) DEFAULT NULL,
  `id_b` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

使用过的表格数据

INSERT INTO `TableA` (`id_a`)
VALUES (1), (2), (3), (4), (5);

INSERT INTO `TableB` (`id_b`, `id_o`)
VALUES (1,2), (2,2), (3,2), (4,5), (5,8), (6,2), (7,5), (8,1);

INSERT INTO `TableC` (`id_a`, `id_b`)
VALUES (1,3), (1,2), (3,6), (2,8), (4,4), (4,7);
祝你好运。

答案 1 :(得分:0)

我认为你很接近:

SELECT c.id_a, MAX(b.id_o) as id_o
FROM TableC c JOIN
     TableB b
     ON c.id_b = b.id_b
GROUP BY c.id_a
HAVING MIN(id_o) = MAX(id_o);

这仅由id_a聚合。它会检查id_o是否只有id_a的一个值。另一种方法是在COUNT(DISTINCT id_o) = 1子句中使用FROM。但是,COUNT(DISTINCT)会产生比简单MAX()MIN()更多的开销。

答案 2 :(得分:0)

我会使用distinct并对您的解决方案进行一些修改

SELECT c.id_a, MAX(b.id_o)
FROM  TableC c
JOIN  TableB b ON  c.id_b = b.id_b
GROUP BY c.id_a
HAVING COUNT(distinct id_o) = 1;
相关问题