SQL Server 2008:根据条件选择成员组

时间:2014-02-27 17:31:01

标签: sql-server group-by

我有一张桌子

CREATE TABLE #tblA (mem_id int, type varchar(20), address1 varchar(20),group_id int)

insert into #tblA (mem_id, type, address1,group_id)
values (1,'self','abc St',1),
       (2,'Child','abc St',1),
       (3,'Child','xyz st',1),
       (4,'spouse','pqr st',1),
       (5,'Child','abc St',1),
       (6,'Child','xyz st',1),

       (7,'self','mno st',2),
       (8,'Child','def St',2),
       (9,'Child','def st',2),

       (10,'self','loi st',3),
       (11,'Child','loi St',3),
       (12,'Child','ewr st',3)

       (13,'self','ooo st',NULL),

所以,我想选择:

  1. 对于每个组,请选择“self”。
  2. 如果没有组,请选择自己。
  3. 如果其他人住在与自己不同的地址,请选择这些 成员。
  4. 如果多个成员住在不同的地址,请选择1名成员 在不同的地址
  5. 预期结果:

       (1,'self','abc St',1),
       (3,'Child','xyz st',1),
       (4,'spouse','pqr st',1),
       (7,'self','mno st',2),
       (8,'Child','def St',2),
       (10,'self','loi st',3),
       (12,'Child','ewr st',3)
       (13,'self','ooo st',NULL),
    

    由于

    我的代码:不工作:

    select  
       mem_id
    from 
       (select 
            a.*,
            RANK() over (partition by group_id order by AddressCnt DESC) as AddressRank
        from 
            (select 
                 a.*,
                 (case when max(address1) over (partition by group_id) = min(address1) over (partition by group_id)
                  then 1 else 0
                  end) as AddressSame,
                 count(*) over (partition by group_id, address1) as AddressCnt
             from #tblA a) a
       ) a
    where 
       (AddressSame = 1 or type in ('Self') or
        (AddressRank > 1 OR  type in ('Self') or group_id is null 
    

2 个答案:

答案 0 :(得分:2)

这是一个解决方案。

  • 创建一个识别“自我”记录的CTE。
  • 使用从self到tableA的连接创建另一个标识“其他”的cte
  • 使用row_number只查找其他
  • 的一条记录
  • 联合两个cte的


WITH self 
     AS (SELECT * 
         FROM   tbla 
         WHERE  type = 'self'), 
     others 
     AS (SELECT a.mem_id, 
                a.type, 
                a.address1, 
                a.group_id, 
                Row_number() 
                  OVER ( 
                    partition BY a.group_id, a.address1 
                    ORDER BY a.mem_id) rn 
         FROM   self s 
                INNER JOIN tbla a 
                        ON s.group_id = a.group_id 
                           AND s.mem_id <> a.mem_id --Exclude self records
                           AND s.address1 <> a.address1 --Exclude the same address as self) 
SELECT mem_id, 
       type, 
       address1, 
       group_id 
FROM   self 
UNION 
SELECT mem_id, 
       type, 
       address1, 
       group_id 
FROM   others 
WHERE  rn = 1 
ORDER  BY mem_id 

DEMO

答案 1 :(得分:0)

此MySQL查询提供了所需的输出:

从tblA中选择*,其中type ='self'UNION select * from tblA group by address1,address1 not in in(select address1 from tblA where type ='self')ORDER by mem_id;