从一列中只为另一个列中的每个值选择一个值,以及对应的其他列值

时间:2018-08-04 05:10:47

标签: sql sql-server

这似乎是一个非常简单的问题,但我无法解决它,假设我有下表:

ID  MessageId   ReceiverId
----------------------------
1   1           1
2   1           2
3   2           3
4   3           1
5   3           2

我想在MessageId列中有一个唯一值的结果,这意味着MessageId的只有一行是1,无论哪一行。 像这样的东西:

ID  MessageId   ReceiverId
----------------------------
1   1           1
3   2           3
4   3           1

如果我只需要返回一列,那么我将不使用GROUP BY

6 个答案:

答案 0 :(得分:1)

似乎您需要 correlated 子查询:

select m.*
from msg m
where id = (select top (1) id
            from msg m1 
            where m1.messageid = m.messageid
            order by m1.ReceiverId 
           );

答案 1 :(得分:1)

select id, messageId, receiverId
from
(
    select *,
           row_number() over(partition by messageId order by id) rnum
    from @t
) x
where x.rnum = 1;

答案 2 :(得分:0)

为了获得最佳性能,需要使用CTE。让我们首先使用脚本创建表:

 CREATE TABLE MyMessages(ID INT PRIMARY KEY ,  MessageId INT,   ReceiverId INT )
 GO 

INSERT INTO MyMessages values(1 ,  1 ,  1)
INSERT INTO MyMessages values(2 ,  1 ,  2)
INSERT INTO MyMessages values(3 ,  2 ,  3)
INSERT INTO MyMessages values(4 ,  3 ,  1)
INSERT INTO MyMessages values(5 ,  3 ,  2)

我认为该查询对您来说很好。

;WITH UniqueMessages AS (SELECT MIN(ID) AS FirstID FROM MyMessages AS MM GROUP BY MM.MessageId)

SELECT  MM.ID, MM.MessageId, MM.ReceiverId 
FROM UniqueMessages AS UM 
INNER JOIN MyMessages AS MM ON MM.ID = UM.FirstID

答案 3 :(得分:0)

您可以将CTERANK一起使用

CREATE TABLE #test(ID INT, MessageId INT,  ReceiverId INT)
INSERT INTO #test VALUES
(1,1,1),
(2,1,2),
(3,2,3),
(4,3,1),
(5,3,2)

WITH val AS (
    SELECT *, RANK() OVER(PARTITION BY MessageId ORDER BY ID) rnk
    FROM #test
    )
SELECT ID, MessageId, ReceiverId 
FROM val WHERE rnk = 1

输出:

ID  MessageId   ReceiverId
1   1           1
3   2           3
4   3           1

答案 4 :(得分:0)

SELECT *
FROM #myTable
WHERE ID IN
      (
          SELECT MIN(ID) FROM #myTable GROUP BY MessageId
      );

答案 5 :(得分:0)

假设一行只能出现两次,我建议:

select m.*
from msgs m
where MessageId < ReceiverId
union all
select m.*
from msgs m
where MessageId > ReceiverId and
      not exists (select 1
                  from msgs m2
                  where m2.MessageId = m.ReceiverId and
                        m2.ReceiverId = m.MessageId
                 ); 

如果确实有两行以上,则可以使用不需要子查询的此解决方案:

select top (1) with ties m.*
from msgs m
order by row_number() over (order by case when MessageId < ReceiverId then MessageId 
                                           else ReceiverId
                                      end
                           );