【问题标题】:Remove dups on one side but not on the other in SQL JOIN在 SQL JOIN 中删除一侧而不是另一侧的 dups
【发布时间】:2012-06-17 23:47:33
【问题描述】:

代码更新: 在#left 表中添加了 [score] 列。连接必须从#left 表中提取学生姓名分数。任何一个分数都可以,但不应拉取重复的 student_id。我在想 cursor 可以做到吗?


我正在运行此报告。问题类似于我创建的脚本。总而言之,我有两张表,我们称之为#left 和#right。 #right 表是包含金额的关键表。但是#left 表包含我也必须检索的代理名称。

create table #left (
id int not null primary key identity,
student_id int, name varchar(20),score int)

insert into #left values( 1, 'James',10)
insert into #left values( 2, 'Parker',20)
insert into #left values( 3, 'Smith',30)
insert into #left values( 4, 'Rog',40)
insert into #left values( 1, 'James',50)
insert into #left values( 2, 'Parker',60)

create table #right (
id int not null primary key identity,
student_id int,
amount decimal(5,2)
)

insert into #right values (1,5.25)
insert into #right values (3,7.25)
insert into #right values (4,3.25)
insert into #right values (1,5.25)

这里的问题是我想加入 student_id 上的两个表,但是你可以看到 #left 表包含 James 和 Parker 2 次具有相同的 id。让我们假设这是数据库错误。

#right 表中可能存在类似问题。但这不是一个错误。它只是意味着#left 学生与两次付款相关联(即使两次付款相同)。

我想从 #left 表中删除 dups 并将 dups 保留在 #right 表中。

我想出了这个查询,它有效

/* query 1 */
select student_id, amount from #right R
where exists
(
select student_id from #left L
where R.student_id = L.student_id
);

但这里的问题是我还需要从另一个表中提取学生姓名。有没有办法做到这一点。它可以是任何语法,但需要高效的查询。

【问题讨论】:

  • 如果在人们解决了您的原始问题后您的问题发生了变化,请不要更改问题。请换一个新的。

标签: sql sql-server-2005 join duplicate-removal


【解决方案1】:

这应该可行:

原问题的解决方案

#left 表看起来像这样

create table #left (
id int not null primary key identity,
student_id int, name varchar(20))

insert into #left values( 1, 'James')
insert into #left values( 2, 'Parker')
insert into #left values( 3, 'Smith')
insert into #left values( 4, 'Rog')
insert into #left values( 1, 'James')
insert into #left values( 2, 'Parker')

查询:1

SELECT A.student_id, A.amount, B.name
FROM #right A
LEFT JOIN (SELECT DISTINCT student_id, name FROM #left) B
ON A.student_id = B.student_id

更新到修改后的标准好吧,如果任何分数都很好,那么你可以这样做:

查询:2

SELECT A.student_id, A.amount, B.name, B.score
FROM #right A
LEFT JOIN ( SELECT student_id, name, MIN(score) score
            FROM #left
            group by student_id, name) B
ON A.student_id = B.student_id

【讨论】:

  • 这行得通,但我想我要在这里修改我的模型。如果我在实际问题中使用 distinct,它包含一个不同的字段,因此会提取更多记录。我会更新我的问题。到目前为止 +1 :)
  • @Thecrocodilehunter - 好的,那我想我得等你更新你的帖子了
  • 我基本上需要这样的逻辑:我正在遍历#right 表,如果#left 表中存在基于student_id 的记录,那么我还包括#left 表中的一些字段以完成我的查询。
  • @Thecrocodilehunter - 这就是我发布的答案正在做的事情。如果您想要不同的东西,请将您的预期数据作为示例发布,以便我们为您提供帮助
  • @Thecrocodilehunter:还要考虑是否应该问另一个正确问题...
【解决方案2】:

如果存在没有付款的学生(#right 表中没有行),您应该从我认为加入的#left 表开始。为了避免重复的学生行,您可以使用已建议的 distinct 或 group by 等聚合函数。

我的想法的一些未经测试的代码:

select name, id, amount from
  (
    (select max(left.name) as name, left.student_id as id
      from #left left
      group by left.student_id)
        left join #right right on left.student_id = right.student_id
  )

【讨论】:

    猜你喜欢
    • 2019-04-06
    • 2015-12-16
    • 2012-11-14
    • 2017-10-31
    • 2014-05-21
    • 1970-01-01
    • 2011-02-11
    • 1970-01-01
    • 2016-04-21
    相关资源
    最近更新 更多