显示前n个记录,巩固行的其余部分(Display top n records and consoli

2019-09-22 08:30发布

我是比较新的编写SQL。 我有一个要求,我必须显示前5个记录,因为它是和巩固其余为1条单记录,并追加其为公司第六届记录。 我知道前5选择的前5名的记录,但我发现很难把一个逻辑巩固记录的其余部分,并在结果集的底部添加它。

weekof          sales    year    weekno
-------------------------------------------------------------
07/01 - 07/07   2   2012    26  
07/08 - 07/14   2   2012    27  
07/29 - 08/04   1   2012    30  
08/05 - 08/11   1   2012    31  
08/12 - 08/18   32  2012    32  
08/26 - 09/01   2   2012    34  
09/02 - 09/08   8   2012    35  
09/09 - 09/15   46  2012    36   
09/16 - 09/22   26  2012    37

我想这显示为

weekof          sales
----------------------
09/16 - 09/22   26  
09/09 - 09/15   46  
09/02 - 09/08   8   
08/26 - 09/01   2   
08/12 - 08/18   32  
07/01 - 08/11   6

Answer 1:

除了当weekof跨越年,这会得到你想要的数据,并以正确的顺序:

;WITH x AS 
(
  SELECT weekof, sales, 
    rn = ROW_NUMBER() OVER (ORDER BY [year] DESC, weekno DESC) 
  FROM dbo.table_name
)
SELECT weekof, sales FROM x WHERE rn <= 5
UNION ALL
SELECT MIN(LEFT(weekof, 5)) + ' - ' + MAX(RIGHT(weekof, 5)), SUM(sales)
FROM x WHERE rn > 5    
ORDER BY weekof DESC;

当返回跨度的行一年,你可能不得不返回RN以及(和忽略它在表示层):

;WITH x AS 
(
  SELECT weekof, sales, 
    rn = ROW_NUMBER() OVER (ORDER BY [year] DESC, weekno DESC) 
  FROM dbo.table_name
)
SELECT weekof, sales, rn FROM x WHERE rn <= 5
UNION ALL
SELECT MIN(LEFT(weekof, 5)) + ' - ' + MAX(RIGHT(weekof, 5)), SUM(sales), rn = 6 
FROM x WHERE rn > 5
ORDER BY rn;


Answer 2:

这里的交叉年甚至时显示正确的顺序的替代版本,并且需要单次扫描,而不是两个(重要仅当数据量很大)。 它将在2005年SQL和后续工作:

WITH Sales AS (
   SELECT
      Seq = Row_Number() OVER (ORDER BY S.yr DESC, S.weekno DESC),
      *
   FROM dbo.SalesByWeek S
)
SELECT
   weekof =
      Substring(Min(Convert(varchar(11), S.yr) + Left(S.weekof, 5)), 5, 5)
      + ' - '
      + Substring(Max(Convert(varchar(11), S.yr) + Right(S.weekof, 5)), 5, 5),
   sales = Sum(S.sales)
FROM
   Sales S
   OUTER APPLY (SELECT S.Seq WHERE S.Seq <= 5) G
GROUP BY G.Seq   
ORDER BY Coalesce(G.Seq, 2147483647)
;

还有可能的查询可能会非常大的数据集表现得更好,因为它不会(TOP使用一次,而)计算行数。 但是,这是所有的理论没有真正的数据和性能测试:

SELECT
   weekof =
      Substring(Min(Convert(varchar(11), S.yr) + Left(S.weekof, 5)), 5, 5)
      + ' - '
      + Substring(Max(Convert(varchar(11), S.yr) + Right(S.weekof, 5)), 5, 5),
   sales = Sum(S.sales)
FROM
   dbo.SalesByWeek S
   LEFT JOIN (
      SELECT TOP 5 *
      FROM dbo.SalesByWeek
      ORDER BY yr DESC, weekno DESC
   ) G ON S.yr = G.yr AND S.weekno = G.weekno
GROUP BY G.yr, G.weekno
ORDER BY Coalesce(G.yr, 9999), G.weekno
;

最终,我真的不喜欢的字符串操作拉出日期范围。 它会更好,如果该表具有MinDateMaxDate作为单独的列,然后创建一个标签,对他们来说就会简单得多。



文章来源: Display top n records and consolidate the rest of the rows