连接表时删除重复项

时间:2012-10-23 10:56:19

标签: sql database postgresql

我有一个新闻表如下

新闻:

| id  | title                       | description
| 1   | Breaking news               | bla bla bla
| 2   | Heavy snowfall in london    | bla bla bla

一个Type表如下:

| id  | type_name   | type_code
| 1   | weather     | 0567
| 2   | city        | 0653

和一个NewsType表如下

|id | news_id | type_id | created_by |
| 1 | 2       | 1       | "John"     |
| 2 | 2       | 2       | "Alex"     |

从NewsType表中可以看出,单个新闻可以分为两种或更多类型。

我需要显示与类型相对应的新闻。用户可能会说给我关于城市和天气的所有新闻。要显示这个,我正在做类似的事情:

      select distinct n.* , nt.created_at
      from news n, newstype nt, type t where
      n.id = nt.news_id and
      t.id = nt.type_id 
      order by nt.created_at
      limit 25

问题是这个查询两次返回相同的消息(我认为这是因为我正在做的内连接)。我应该在查询中更改什么,以便如果新闻被分类为两种类型,并且用户请求查看相同的两种类型的新闻,我只获得单个新闻项?而不是两个!

5 个答案:

答案 0 :(得分:5)

简单的解决方案:

select * from news where news_id in (
select news_id 
from NewsType 
where type_id in (the types you want)
)

大多数人会说你应该在内部查询的news_id上添加一个DISTINCT。你可以试试,但我很确定它会降低性能。

总而言之,如果您认为此解决方案效果不佳,您可以将内部查询设置为CTE,这通常表现得更好:

with my_CTE as(
    select news_id 
    from NewsType 
    where type_id in (the types you want)
)
select * 
from news 
where news_id in (select news_id  from my_CTE)

答案 1 :(得分:2)

group by是另一种方法:

select n.id, n.title, n.description, max(nt.created_at)
      from news n, newstype nt, type t where
      n.id = nt.news_id and
      t.id = nt.type_id
      group by n.id, n.title, n.description
      order by nt.created_at
      limit 25

答案 2 :(得分:0)

您想要选择具有针对特定类型的NewsType表中的条目的所有故事。因此,您希望选择与该类型存在关系的新闻项目:

SELECT
    News.ID,
    News.Title,
    News.Description
FROM
    News
WHERE
    EXISTS
    (SELECT
        NULL
    FROM
        NewsType
        INNER JOIN Type ON NewsType.Type_ID = Type.ID
    WHERE
        News.ID = NewsType.News_ID
    AND Type.Type_Code = @typeCode)

如果使用类型名称作为参数,则可能需要将where子句的最后一行更改为Type.Type_Name = @typeName

答案 3 :(得分:0)

尝试

select distinct n.id, n.title, n.description

但是,正如@Jan Dvorak所说,

select distinct n.*

不应该选择相同的新闻两次

答案 4 :(得分:0)

您需要决定如何处理“重复”类型:您是否只想为与多种类型相关联的新闻项目显示一种类型,或者您是否要将它们全部列出?

如果是后者,您可以使用string_agg函数进行调查,请参阅http://www.postgresql.org/docs/9.2/static/functions-aggregate.html

select distinct n.id, n.title, n.description, string_agg(t.type_name, ',')
from news n, newstype nt, type t where
n.id = nt.news_id and
t.id = nt.type_id
group by n.id, n.title, n.description
limit 25