【问题标题】:Is there a way to present top 5 and bottom 5 and the order by a column?有没有办法按列显示前 5 名和后 5 名以及顺序?
【发布时间】:2021-11-28 20:19:44
【问题描述】:

有没有办法按列显示前 5 和后 5 以及顺序?

我有 2 个查询如下所示:

SELECT * 
FROM
    (SELECT DISTINCT TOP(5) 
         OG.GAMES AS 'Olympic Games', OC.CITY AS 'Hosting City', 
         OG.Expenses_Mil AS 'Financial Expenses (in multiples of 1M$)' 
     FROM 
         [Olympics].[Events_Facts] AS OEF 
     JOIN 
         [Olympics].[Games] AS OG ON OEF.GAMES_ID = OG.GAMES_ID
     JOIN 
         [Olympics].[Cities] AS OC ON OEF.CITY_ID = OC.CITY_ID
     ORDER BY 
         OG.Expenses_Mil DESC) A

UNION ALL

SELECT * 
FROM 
    (SELECT DISTINCT TOP(5) 
         OG.GAMES AS 'Olympic Games', OC.CITY AS 'Hosting City', 
         OG.Expenses_Mil AS 'Financial Expenses (in multiples of 1M$)' 
     FROM 
         [Olympics].[Events_Facts] AS OEF 
     JOIN 
         [Olympics].[Games] AS OG ON OEF.GAMES_ID = OG.GAMES_ID
     JOIN 
         [Olympics].[Cities] AS OC ON OEF.CITY_ID = OC.CITY_ID
     ORDER BY 
         OG.Expenses_Mil) B

我希望最终输出以DESC 的顺序对费用列进行排序,但我无法对嵌套列进行操作。

输出是:

2016 Summer Rio de Janeiro    10
2014 Winter Sochi              8.2
2012 Summer London             8
2002 Winter Salt Lake City     7
2004 Summer Athina             7
1900 Summer Paris              1
1904 Summer St. Louis          1
1906 Summer Athina             1
1912 Summer Stockholm          1.3
1920 Summer Antwerpen          1.4

而所需的输出应根据最后一列按 DESC 顺序排列

【问题讨论】:

  • 请提供minimal reproducible example 示例数据和所需结果。
  • 你的意思是显示每一行的rank
  • 在上面的查询中,我想在显示前 5 个值(og.expenses)和后 5 个值的查询之间进行联合。然后用 DESC order 对最后的费用列进行排序
  • Events_Facts 如何进入此查询,您没有选择任何列?表之间的关系是什么,为什么需要DISTINCT,你是否得到重复的行?也许你应该重新考虑你的加入
  • Events_Facts 是其他表之间的连接表。和DISTINCT 是为了摆脱重复。

标签: sql sql-server tsql


【解决方案1】:

您可以使用窗口函数row_number() over()。如果碰巧有联系,并且您想看到它们...您可以改用dense_rank()

示例

with cte as (
SELECT OG.GAMES AS [Olympic Games]
     , OC.CITY AS [Hosting City]
     , OG.Expenses_Mil AS [Financial Expenses (in multiplies of 1M$)]
     , RN1 = row_number() over (order by OG.Expenses_Mil asc)
     , RN2 = row_number() over (order by OG.Expenses_Mil desc)
FROM [Olympics].[Events_Facts] AS OEF 
JOIN [Olympics].[Games]  AS OG ON OEF.GAMES_ID = OG.GAMES_ID
JOIN [Olympics].[Cities] AS OC ON OEF.CITY_ID = OC.CITY_ID
)
Select [Olympic Games]
      ,[Hosting City]
      ,[Financial Expenses (in multiplies of 1M$)]
 From  cte 
 Where RN1<=5
    or RN2<=5
 Order by [Financial Expenses (in multiplies of 1M$)] desc

附注:窗口函数非常宝贵。它们非常值得您花时间熟悉它们。

【讨论】:

  • 这个查询给出了不正确的输出@john cappelletti
  • @Aby_g 如果没有更多信息,我不确定我能否提供帮助。这是您的查询。我们不做 UNION ALL,而是对费用进行排名(asc 和 desc)。
【解决方案2】:

@JohnCappelletti's answer 很好。但是它确实需要两种排序,一次用于升序,一次用于降序。

这是一个使用单一排序的解决方案:

我们使用带有偏移量的LEAD 来检查后面的 5 行是否丢失。

with cte as (
  SELECT OG.GAMES AS [Olympic Games]
       , OC.CITY AS [Hosting City]
       , OG.Expenses_Mil AS [Financial Expenses (in multiplies of 1M$)]
       , RN = row_number() over (order by OG.Expenses_Mil desc)
       , ID5 = lead(OEF.ID, 5) over (order by OG.Expenses_Mil desc)
  FROM [Olympics].[Events_Facts] AS OEF 
  JOIN [Olympics].[Games]  AS OG ON OEF.GAMES_ID = OG.GAMES_ID
  JOIN [Olympics].[Cities] AS OC ON OEF.CITY_ID = OC.CITY_ID
)
Select [Olympic Games]
      ,[Hosting City]
      ,[Financial Expenses (in multiplies of 1M$)]
 From  cte 
 Where RN <= 5
    or ID5 IS NULL
 Order by [Financial Expenses (in multiplies of 1M$)] desc

【讨论】:

  • 您的查询看起来不错,但没有 OEF.ID 列
  • 好的,你可以使用另一列NOT NULL,最好是主键
【解决方案3】:

我找到了解决 SP 问题的原始方法:

CREATE PROCEDURE OLYMPIC_UNION_ORDERBY
AS  
SELECT * FROM

(SELECT DISTINCT TOP(5) OG.GAMES AS 'Olympic Games', OC.CITY AS 'Hosting City', OG.Expenses_Mil AS 'Financial Expenses (in multiplies of 1M$)' 
FROM [Olympics].[Events_Facts] AS OEF JOIN [Olympics].[Games]  AS OG
     ON OEF.GAMES_ID = OG.GAMES_ID
     JOIN [Olympics].[Cities] AS OC
     ON OEF.CITY_ID = OC.CITY_ID
ORDER BY OG.Expenses_Mil DESC) A

UNION ALL

SELECT * FROM 

(SELECT DISTINCT TOP(5) OG.GAMES AS 'Olympic Games', OC.CITY AS 'Hosting City', OG.Expenses_Mil AS 'Financial Expenses (in multiplies of 1M$)' 
FROM [Olympics].[Events_Facts] AS OEF JOIN [Olympics].[Games]  AS OG
     ON OEF.GAMES_ID = OG.GAMES_ID
     JOIN [Olympics].[Cities] AS OC
     ON OEF.CITY_ID = OC.CITY_ID
ORDER BY OG.Expenses_Mil) B
;

EXEC OLYMPIC_UNION_ORDERBY

CREATE TABLE  TempTable
(OUTPUT1 VARCHAR(MAX),
 OUTPUT2 VARCHAR(MAX),
 OUTPUT3 FLOAT
)

INSERT INTO TempTable
EXEC OLYMPIC_UNION_ORDERBY

SELECT * 
FROM TempTable
ORDER BY OUTPUT3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多