加入两个表并删除重复项

时间:2014-08-04 10:16:32

标签: mysql sql postgresql row-number

我试图加入两张桌子。 table2有duplates。

表格看起来像

CREATE TABLE ta 
    (
     id int, 
     cno varchar(30),
     d1 varchar(30),
     d2 int
    );
CREATE TABLE tb 
    (
     id int, 
     cno varchar(30),
     cn1 varchar(30),
     cn2 int
    );

INSERT INTO ta
(id, cno, d1, d2)
VALUES
(1, '1234','a',2),
(2, '6456','j',3),
(3, '5456','h',4),
(4, '4454','g',5);

INSERT INTO tb
(id, cno, cn1, cn2)
VALUES
(1, '1234', 'a', 21),
(1, '1234', 'a', 22),
(2, '6456', 'b', 33),
(2, '6456', 'c', 34),
(2, '6456', 'c', 35),
(3, '5456', 'c', 36),
(4, '4454', 'c', 37);

我能够在MySQL中获得结果http://sqlfiddle.com/#!2/b282e3/1。但是,当我在Postgresql中运行它时,我收到错误http://sqlfiddle.com/#!15/b282e/4

输出应该像http://sqlfiddle.com/#!2/b282e3/1

CNO     CN1 CN2 D1  D2
1234    a   21  a   2
4454    c   37  g   5
5456    c   36  h   4
6456    b   33  j   3

Psql中的任何替代方法?

4 个答案:

答案 0 :(得分:1)

对GROUP BY中未使用的列使用聚合函数:

select t2.cno,
min(t2.cn1) as a,
min(t2.cn2) as b,
min(t1.d1) as c,
min(t1.d2) as d
from ta as t1
inner join tb as t2
on t1.cno=t2.cno
group by t2.cno

http://sqlfiddle.com/#!15/b282e/23

答案 1 :(得分:1)

MySQL中的这个查询:

select t2.cno, t2.cn1, t2.cn2, t1.d1, t1.d2
from ta t1 inner join
     tb t2
     on t1.cno = t2.cno
group by t2.cno;

是无效的SQL(根据标准或其他数据库)。问题是select中的列既不在group by也不是聚合函数的参数(并且它们不是"功能依赖"或者)。我们官方不鼓励您在MySQL中使用group by扩展名。您可以阅读有关它的文档here

具有讽刺意味的是,Postgres有一个名为distinct on的扩展,可以做类似的事情。语法是:

select distinct on (t2.cno) t2.cno, t2.cn1, t2.cn2, t1.d1, t1.d2
from ta t1 inner join
     tb t2
     on t1.cno = t2.cno
order by t2.cno;

distinct on在括号中列出一个列表,并在括号中每个值返回一行 - 取第一行而忽略其余行。这些列需要匹配order by中的列,否则Postgres会生成编译时错误。

在大多数其他数据库中,您可以使用row_number()执行类似操作。你也可以在Postgres中使用它。

答案 2 :(得分:0)

select t2.cno, min (t2.cn1), min(t2.cn2), t1.d1 , t1.d2
from ta as t1
inner join tb as t2 on t1.cno=t2.cno
group by t2.cno, t1.d1 , t1.d2

答案 3 :(得分:0)

WITH Queries (Common Table Expressions)

    with cte as 
    (
      select cno,cn1,cn2 from tb where cn2 in (select min(cn2) from tb group by cno) 
    ),
    cte1 as 
      (
        select d1,d2,cno from ta where cno in (select cno from tb where cn2 in (select    
        min(cn2) from tb group by cno))
      )
    select cte.cno,cn1,cn2,d1,d2 from cte inner join cte1 on cte1.cno = cte.cno order  
    by cte.cno