2014-09-11 91 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