Sql 如何删除重复的结果

Sql 如何删除重复的结果,sql,postgresql,Sql,Postgresql,给定以下模式: CREATE TABLE IF NOT EXISTS companies ( id serial, name text NOT NULL, PRIMARY KEY (id) ); CREATE TABLE IF NOT EXISTS cars ( id serial, make text NOT NULL, year integer NOT NULL, company_id INTEGER REFERENCES companies(id),

给定以下模式:

CREATE TABLE IF NOT EXISTS companies (
  id serial,
  name text NOT NULL,

  PRIMARY KEY (id)
);

CREATE TABLE IF NOT EXISTS cars (
  id serial,
  make text NOT NULL,
  year integer NOT NULL,
  company_id INTEGER REFERENCES companies(id),

  PRIMARY KEY (id)
);


INSERT INTO companies (id, name) VALUES
  (1, 'toyota'),
  (2, 'chevy');

INSERT INTO cars (make, year, company_id) VALUES
  ('silverado', 1995, 2),
  ('malibu', 1999, 2),
  ('tacoma', 2017, 1),
  ('custom truck', 2010, null),
  ('van custom', 2005, null);
如何为汽车选择行,仅显示给定公司的最新汽车

e、 g

输出

     make     | model  | year 
--------------+--------+------
 custom truck |        | 2010
 malibu       | chevy  | 1999
 silverado    | chevy  | 1995
 tacoma       | toyota | 2017
 van custom   |        | 2005
但我只想展示最新的“雪佛兰”,例如

并且仍然能够按“制造”进行排序,并显示没有空公司id的汽车

小提琴链接:
借助常用的表表达式和行数函数,我们可以得到所需的输出,下面是给出所需输出的查询

     WITH temp AS 
    (SELECT 
        make
        , companies.name AS model
        , year
        , row_number() over(PARTITION BY coalesce(companies.name, make) ORDER BY year desc) as rnk
    FROM   
       cars
    left join 
       companies
    ON 
       companies.id = cars.company_id
    )
    SELECT 
       make
       , model
       , year
    FROM
       temp
    WHERE
       rnk = 1
    ;  

借助常用的表表达式和行数函数,我们可以得到所需的输出,下面是给出所需输出的查询

     WITH temp AS 
    (SELECT 
        make
        , companies.name AS model
        , year
        , row_number() over(PARTITION BY coalesce(companies.name, make) ORDER BY year desc) as rnk
    FROM   
       cars
    left join 
       companies
    ON 
       companies.id = cars.company_id
    )
    SELECT 
       make
       , model
       , year
    FROM
       temp
    WHERE
       rnk = 1
    ;  

SQL可以基于集合数学(离散数学)完成。因此,您需要所有汽车的集合减去其年份小于给定公司id的最大年份的汽车集合

所有车辆的集合:

select * from cars
年份小于给定公司id的最大年份的所有车辆的集合:

select a.id from cars a, cars b where a.company_id = b.company_id  and a.year < b.year

SQL可以基于集合数学(离散数学)完成。因此,您需要所有汽车的集合减去其年份小于给定公司id的最大年份的汽车集合

所有车辆的集合:

select * from cars
年份小于给定公司id的最大年份的所有车辆的集合:

select a.id from cars a, cars b where a.company_id = b.company_id  and a.year < b.year

在Postgres中,最好使用
distinct on

select distinct on (co.id) ca.*, co.name as model
from cars ca left join
     companies co
     on ca.company_id = co.id
order by co.id, ca.year desc;
DISTINCT ON
是非常方便的Postgres语法。它在括号中为每个组合保留一行。具体行由
ORDER by
子句确定

但是,您有一个难题,因为
co.id
可以是
null
。在这种情况下,你似乎想让所有的车都无人陪伴

因此:

或者更简单地使用
union all

-- get the ones with a company
select distinct on (co.id) ca.*, co.name
from cars ca join
     companies co
     on ca.company_id = co.id
union all
-- get the ones with no company
select ca.*, null
from cars ca
where ca.company_id is null
order by year desc;
在其他数据库中,这通常使用
行编号()来完成:


在Postgres中,最好使用
distinct on

select distinct on (co.id) ca.*, co.name as model
from cars ca left join
     companies co
     on ca.company_id = co.id
order by co.id, ca.year desc;
DISTINCT ON
是非常方便的Postgres语法。它在括号中为每个组合保留一行。具体行由
ORDER by
子句确定

但是,您有一个难题,因为
co.id
可以是
null
。在这种情况下,你似乎想让所有的车都无人陪伴

因此:

或者更简单地使用
union all

-- get the ones with a company
select distinct on (co.id) ca.*, co.name
from cars ca join
     companies co
     on ca.company_id = co.id
union all
-- get the ones with no company
select ca.*, null
from cars ca
where ca.company_id is null
order by year desc;
在其他数据库中,这通常使用
行编号()来完成:


您的
cars
表没有
model
,但这在您的结果集中。我使用
model
作为
公司的别名。在示例中,name
选择query您的
cars
表没有
model
,但这在您的结果集中。我使用
model
作为公司的别名
companys.name
在示例中选择query可以按品牌或年份对不同的解决方案进行排序吗?@schpet
DISTINCT ON
使用
ORDER BY
定义结果集中的行。如果您想要不同的最终排序,则需要一个子查询/CTE和一个附加的
ORDER BY
。DISTINCT ON解决方案能否按品牌或年份排序?@schpet
DISTINCT ON
使用
ORDER BY
定义结果集中的行。如果您想要不同的最终排序,则需要一个子查询/CTE和一个附加的
orderby
select ca.*
from (select ca.*, co.name as model,
             row_number() over (partition by co.id,
                                             case when co.id is null then ca.id end
                                order by year desc
                               ) as seqnum
      from cars ca left join
           companies co
           on ca.company_id = co.id
     ) ca
where seqnum = 1