2014-09-11 30 views
0

我有表Places与下面的列聚合函数:MIN(),还有一些标准

PlaceId  CityId  Name  Postcode 
----------------------------------------- 
1   1   Place1  NULL 
2   1   Place1  10000 
3   2   Place1  10300 
4   2   Place2  10500 
5   3   Place3  NULL 
6   3   Place3  NULL 

输出我想要的是:

PlaceId  CityId  Name  Postcode 
----------------------------------------- 
2   1   Place1  10000 
3   2   Place1  10300 
4   2   Place2  10500 
5   3   Place3  NULL 

所以,我需要如下:

如果一个城市有CityIdName列重复,那么我需要一行与最小PlaceId。但是,如果两个副本中的第一个在Postcode列中有NULL,并且较大的id在同一列中有一些值,那么我需要输出中的第二行(例如,带有ID 1和2的行,带有ID 2的返回行)。在所有的副本在列邮编NULL值的情况下,那么就返回最小PlaceId(例如,IDS 5和第6行,返回的行ID为5)

所以,列Postcode在最终输出

我影响已经试过这样的:

SELECT 
     MIN(nm.PlaceId) AS PlaceId, 
     nm.CityId, 
     nm.name,   
     COUNT(*) AS Number 
    FROM dbo.Place AS nm 
    GROUP BY 
     nm.CityId , 
     nm.name 

我可以解决这个问题,但解决方案不好,我要求一些漂亮和优雅的解决方案。

+0

什么是邮编的数据类型? – 2014-09-11 09:52:09

回答

1

这个怎么样...

CREATE TABLE #PLACES 
(PlaceId int, CityId int, Name varchar(50), Postcode varchar(50) 
) 
INSERT INTO #PLACES (PlaceId, CityId, Name)VALUES(1, 1, 'Place1') 
INSERT INTO #PLACES (PlaceId, CityId, Name, Postcode)VALUES(2, 1, 'Place1','10000') 
INSERT INTO #PLACES (PlaceId, CityId, Name, Postcode)VALUES(3, 2, 'Place1' , '10300') 
INSERT INTO #PLACES (PlaceId, CityId, Name, Postcode)VALUES(4, 2, 'Place2','10500') 
INSERT INTO #PLACES (PlaceId, CityId, Name)VALUES(5, 3, 'Place3') 
INSERT INTO #PLACES (PlaceId, CityId, Name)VALUES(6, 3, 'Place3') 

- - 查询

​​
+0

为什么接受?这不是OP描述的内容。 – 2014-09-11 11:11:55

1

以下查询应该可以帮助你:

;WITH Places as 
(
    select 1 as PlaceId, 1 as CityId, 'Place1' as Name, NULL as Postcode 
    UNION ALL 
    select 2, 1, 'Place1', 10000 
    UNION ALL 
    select 3, 2, 'Place1', 10300 
    UNION ALL 
    select 4, 2, 'Place2', 10300 
    UNION ALL 
    select 5, 3, 'Place3', NULL 
    UNION ALL 
    select 6, 3, 'Place3', NULL 
) 
SELECT t2.PlaceId, groups.CityId, groups.Name, t2.Postcode FROM (
    select CityId, Name from Places GROUP BY CityId, Name 
    ) groups 
    CROSS APPLY 
    (
     SELECT TOP(1) 
      d2.PlaceId, d2.Postcode, 
      CASE WHEN d2.Postcode IS NOT NULL THEN 1 ELSE 2 END AS RecordPriority 
     FROM Places d2 
     WHERE d2.CityId = groups.CityId AND d2.Name = groups.Name 
     ORDER BY RecordPriority, PlaceId 
    ) t2 ; 

或使用ROW_NUMBER()与上述相同的ORDER BY

;WITH Places AS 
(
... 
), 
OrderedPlaces AS 
(
    SELECT *, 
     Rn = ROW_NUMBER() OVER 
      (PARTITION BY CityId, Name 
      ORDER BY CASE WHEN Postcode IS NOT NULL THEN 1 ELSE 2 END, 
         PlaceID) 
    FROM Places 
) 
SELECT PlaceId, CityId, Name, Postcode 
FROM OrderedPlaces 
WHERE Rn = 1 ; 
+0

你用派生表格过度复杂(不需要t1),但我认为这是正确的,OP想要什么。 – 2014-09-11 10:38:01

+0

感谢@ypercube,我们真的可以简化像这样的查询:SELECT T2 * FROM( 选择CityId,从邻居GROUP BY CityId名称,名称 )组 CROSS APPLY ( SELECT TOP(1)* FROM 的地方d2 WHERE d2.CityId = groups.CityId AND d2.Name = groups.Name ORDER BY CASE when Postcode IS NULL THEN 1 ELSE 2 END DESC,PlaceId )t2 – fastobject 2014-09-11 10:49:03