3

私はSQLを書くことに比較的慣れていません。上位 5 レコードをそのまま表示し、残りを 1 つのレコードとして統合し、6 番目のレコードとして追加する必要があるという要件があります。top 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
4

2 に答える 2

14

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;

返される行が 1 年にまたがる場合、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;
于 2012-09-12T19:35:35.833 に答える
0

これは、年をまたがっても正しい順序で表示され、2 回ではなく 1 回のスキャンが必要な別のバージョンです (データ量が多い場合にのみ重要です)。SQL 2005 以降で動作します。

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 を 1 回使用する) ため、非常に大きなデータ セットに対してさらに優れたパフォーマンスを発揮する可能性のあるクエリもあります。ただし、これはすべて、実際のデータとパフォーマンス テストを行わない理論的なものです。

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が別々の列としてあると、それらのラベルを作成するのがはるかに簡単になります。

于 2013-06-06T01:36:37.207 に答える