我有一个包含各种类别的数据库。对于每个类别,我有三个数量,我想从每个类别的每个数量中提取包含第25个最大值的行(可以安全地忽略关系)。
例如,我可能有一个数据库,其行是来自多个国家之一的城镇或城市。类别是国家,数量可能是人口,土地面积和纬度。然后数据看起来像:
TownName Country Population LandArea Latitude
Paris France 500,715 47.9 45.76
Manchester USA 110,229 90.6 42.99
Calais France 72,589 33.5 50.95
Leicester England 337,653 73.3 52.63
Dunkirk France 90,995 43.9 51.04
... ... ... ... ...
在这个例子中,我想要的最终结果将是列表中的每个国家,以及他们的第25大人口,第25大土地面积和第25大纬度。这不再像某些特定的城镇或城市,而是提供有关每个国家的一些信息。这可能看起来像:
Country Population LandArea Latitude
France 144,548 83.95 50.21
Poland 141,080 88.3 54.17
Australia 68,572 146 -21.35
... ... ... ...
我找到了一种方法来做到这一点,即做以下事情:
使用ROW_NUMBER
功能按降序排列Population,LandArea和Latitude之一,按国家/地区划分。
重复三次(每个数量一次),并将三个数据库JOIN
放在一起。在ON
语句中,确保Country列的值相等,以及rank列的值。
使用WHERE
语句为每个排名为25的国家/地区提取行。
我不喜欢这种方法,因为它涉及创建三个几乎完全相同大小的代码块的副本,以获得我加入的三个独立数据库(连接语句中的每个代码块都是一个不错的大小,因为这是一个简化的例子,我不得不做其他事情来达到这样的阶段。)
我想知道是否有一种方法不会让我用JOIN
语句重复大块代码,因为这会使我的代码变得又大又丑。此外,这似乎可能会一次又一次地出现,所以一种更有效的方法将是美妙的。
感谢您的时间
答案 0 :(得分:1)
也许如果你找不到消除3连接方法的方法,你可以通过为每个不同的元组分配GroupID
来简化连接条件:
;WITH
MasterCTE AS
(
SELECT *,
DENSE_RANK() OVER (ORDER BY Country) AS GroupID -- Don't use ROW_NUMBER here. RANK or DEMSE_RANK only
FROM MyTable
),
cte1 AS
(
SELECT GroupID, [Population],
ROW_NUMBER() OVER (PARTITION BY GroupID ORDER BY [Population] DESC) AS PopulationRank
FROM MasterCTE
),
cte2 AS
(
SELECT GroupID, LandArea,
ROW_NUMBER() OVER (PARTITION BY GroupID ORDER BY LandArea DESC) AS LandAreaRank
FROM MasterCTE
),
cte3 AS
(
SELECT GroupID, Latitude,
ROW_NUMBER() OVER (PARTITION BY GroupID ORDER BY Latitude DESC) AS LatitudeRank
FROM MasterCTE
)
SELECT DISTINCT -- Remember to include DISTINCT
MasterCTE.Country,
cte1.Population, cte2.LandArea, cte3.Latitude
FROM MasterCTE
INNER JOIN cte1 ON MasterCTE.GroupID = cte1.GroupID AND cte1.PopulationRank = 25
INNER JOIN cte2 ON MasterCTE.GroupID = cte2.GroupID AND cte2.LandAreaRank = 25
INNER JOIN cte3 ON MasterCTE.GroupID = cte3.GroupID AND cte3.LatitudeRank = 25