消除具有条件的一列之外的重复行

时间:2017-04-06 10:23:08

标签: sql sql-server

我无法尝试找到适当的查询(SQL-SERVER)来选择带条件的记录,但是我将使用的表有超过100,000行和超过20列。

所以我需要一个满足以下条件的代码:

1.)如果[policy]和[plan]列在行之间是唯一的,那么我将选择该记录

2.)如果[policy]和[plan]返回2行或更多行,那么我将选择'code'列不是999的记录

3.)在某些情况下,不需要的行在[code]列中可能没有'999',但可能是其他细节

换句话说,我想得到第1,2,4,5,7行。

以下是表格的示例

row #|policy|plan|code
-----------------------
  1  |  a   | aa |111
-----------------------
  2  |  b   | bb |112
-----------------------
  3  |  b   | bb |999
-----------------------
  4  |  c   | cc |111
-----------------------
  5  |  c   | cc |112
-----------------------
  6  |  c   | cc |999
-----------------------
  7  |  d   | dd |999
-----------------------

我期待看到像

这样的东西
row #|policy|plan|code
-----------------------
  1  |  a   | aa |111
-----------------------
  2  |  b   | bb |112
-----------------------
  4  |  c   | cc |111
-----------------------
  5  |  c   | cc |112
-----------------------
  7  |  d   | dd |999
-----------------------

提前谢谢

3 个答案:

答案 0 :(得分:4)

这听起来像是优先级查询。您可以使用row_number()

select t.*
from (select t.*,
             row_number() over (partition by policy, plan
                                order by code
                               ) as seqnum
      from t
     ) t
where seqnum = 1;

预期的输出使这一点更清晰:

select t.*
from (select t.*,
             rank() over (partition by policy, plan
                          order by (case when code = 999 then 1 else 2 end) desc
                         ) as seqnum
      from t
     ) t
where seqnum = 1;

OP希望所有代码都不是999,除非唯一的代码是999。所以,另一种方法是:

select t.*
from t
where t.code <> 999
union all
select t.*
from t
where t.code = 999 and
      not exists (select 1
                  from t t2
                  where t2.policy = t.policy and t2.plan = t.plan and
                        t2.code <> 999
                 );

答案 1 :(得分:2)

您可能想要这个(如果不止一个,则删除最后一行)?

select t.*
from (select t.*
            , row_number() over (partition by policy, plan
                          order by code desc
                         ) AS RN
            , COUNT(*) over (partition by policy, plan) AS RC
      from t
     ) t
where RN > 1 OR RN=RC;

输出:

    row policy  plan    code    RN  RC
1   1   a   aa  111 1   1
2   2   b   bb  112 2   2
3   5   c   cc  112 2   3
4   4   c   cc  111 3   3
5   7   d   dd  999 1   1

答案 2 :(得分:0)

CREATE TABLE #Table2
    ([row] int, [policy] varchar(1), [plan] varchar(2), [code] int)
;

INSERT INTO #Table2
    ([row], [policy], [plan], [code])
VALUES
    (1, 'a', 'aa', 111),
    (2, 'b', 'bb', 112),
    (3, 'b', 'bb', 999),
    (4, 'c', 'cc', 111),
    (5, 'c', 'cc', 112),
    (6, 'c', 'cc', 999),
    (7, 'd', 'dd', 999)
;
with cte 
as
(
select *,
 row_number() over (partition by policy, [plan]
                                order by code
                               ) as seqnum
      from #Table2
  )

  select [row], [policy], [plan], [code] from cte where seqnum=1