Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 选择具有多个关系的行_Sql_Postgresql - Fatal编程技术网

Sql 选择具有多个关系的行

Sql 选择具有多个关系的行,sql,postgresql,Sql,Postgresql,鉴于此模式: CREATE TABLE t ( id int, name varchar(200), primary key (id) ); CREATE TABLE t2 ( id int, name varchar(200), primary key (id) ); CREATE TABLE rel ( id1 int, id2 int, value int, primary key (id1, id2), foreign key (id1)

鉴于此模式:

CREATE TABLE t (
  id int,
  name varchar(200),
  primary key (id)
);

CREATE TABLE t2 (
  id int,
  name varchar(200),
  primary key (id)
);

CREATE TABLE rel (
  id1 int,
  id2 int,
  value int,
  primary key (id1, id2),
  foreign key (id1) REFERENCES t(id),
  foreign key (id2) REFERENCES t2(id)
);
我应该如何查询
t
中满足与
t2
的多个关系的行? 这听起来很简单,但我不确定在这种情况下什么是最佳实践。我将通过查询更好地解释:

SELECT t.id, t.name
FROM t
INNER JOIN rel ON (t.id = rel.id1)
INNER JOIN t2 ON (t2.id = rel.id2)
WHERE (rel.id2 = 1 AND rel.value = 1)
当我需要查找满足一个关系的行时,上面的方法非常有效。但现在:

SELECT t.id, t.name
FROM t
INNER JOIN rel ON (t.id = rel.id1)
INNER JOIN t2 ON (t2.id = rel.id2)
WHERE (rel.id2 = 1 AND rel.value = 1)
AND (rel.id2 = 2 AND rel.value = 2)
对于2个关系,此查询将永远不会工作,因为连接的行在一行中永远不会有2个不同的关系,因此它将始终返回
0

到目前为止,我一直在使用的解决方案是查找
t.id
s,它们位于关系的
结果集中:

SELECT t.id, t.name
FROM t
WHERE (t.id IN (SELECT id1 FROM rel WHERE rel.id2 = 1 AND rel.value = 1))
AND (t.id IN (SELECT id1 FROM rel WHERE rel.id2 = 2 AND rel.value = 2))
这是可行的,但是没有更好的办法吗?我觉得我写的SQL太多了,对于这么简单的事情,为每一项做一个子查询似乎有些过头了


这就是所谓的关系划分

SELECT   t.id, t.name
FROM     t 
         INNER JOIN rel
            ON t.id = rel.id1
WHERE    rel.id2 IN (1,2) AND
         rel.value = 1
GROUP BY t.id, t.name
HAVING   COUNT(rel.id2) = 2

    • 这称为关系划分

      SELECT   t.id, t.name
      FROM     t 
               INNER JOIN rel
                  ON t.id = rel.id1
      WHERE    rel.id2 IN (1,2) AND
               rel.value = 1
      GROUP BY t.id, t.name
      HAVING   COUNT(rel.id2) = 2
      

      我可能过于简化了这个问题,但您不能在where子句中将
      更改为
      ,并使用
      分组/拥有
      来获取给定条件下的关系数。e、 g

      SELECT  t.id, t.name
      FROM    t
              INNER JOIN rel 
                  ON t.id = rel.id1
              INNER JOIN t2 
                  ON t2.id = rel.id2
      WHERE   (rel.id2 = 1 AND rel.value = 1)
      OR      (rel.id2 = 2 AND rel.value = 1)
      GROUP BY t.Id, t.Name
      HAVING COUNT(*) = 2;
      
      尽管我将where条款改写为:

      WHERE   rel.Value = 1 
      AND     rel.ID2 IN (1, 2)
      
      编辑

      我将不再用经过编辑的问题重写上面的where子句。它将成为

      WHERE   (rel.id2 = 1 AND rel.value = 1)
      OR      (rel.id2 = 2 AND rel.value = 2)
      

      我可能过于简化了这个问题,但您是否可以在where子句中将
      更改为
      ,并使用
      GROUP BY/HAVING
      获取给定条件下的关系数。e、 g

      SELECT  t.id, t.name
      FROM    t
              INNER JOIN rel 
                  ON t.id = rel.id1
              INNER JOIN t2 
                  ON t2.id = rel.id2
      WHERE   (rel.id2 = 1 AND rel.value = 1)
      OR      (rel.id2 = 2 AND rel.value = 1)
      GROUP BY t.Id, t.Name
      HAVING COUNT(*) = 2;
      
      尽管我将where条款改写为:

      WHERE   rel.Value = 1 
      AND     rel.ID2 IN (1, 2)
      
      编辑

      我将不再用经过编辑的问题重写上面的where子句。它将成为

      WHERE   (rel.id2 = 1 AND rel.value = 1)
      OR      (rel.id2 = 2 AND rel.value = 2)
      

      我的问题看起来不错,但是如果这些关系有完全不同的值呢?这就是我的实际用例。你能扩展这个关系吗?更多的关系有完全不同的值吗?我将第二个关系的值更改为2,这样它应该将
      t
      中的行与
      (rel.id2=1和rel.value=1)和(rel.id2=2和rel.value=2)的关系匹配起来
      +1稍后我将花时间通读关系划分文章。我的问题看起来没问题,但如果关系具有完全不同的值怎么办?这就是我的实际用例。你能扩展这个关系吗?更多的关系有完全不同的值吗?我将第二个关系的值更改为2,这样它应该将
      t
      中的行与
      (rel.id2=1和rel.value=1)和(rel.id2=2和rel.value=2)的关系匹配起来
      +1我稍后会花时间通读关系部门的文章。哦,没关系,是另一个人发布并删除了一个带有
      计数(*)1的答案,尽管如此,似乎确实做到了这一点。哦,没关系,是另一个人发布并删除了带有
      计数(*)1的答案,然而,似乎确实做到了这一点。