3

次の2つのテーブルがあります。

CREATE TABLE #SalesByStore (
    Brand VARCHAR(10),
    StoreName VARCHAR(50),
    Sales DECIMAL(10,2)
)

CREATE TABLE #SalesByBrand (
    Brand VARCHAR(10),
    TotalSales DECIMAL(10,2)
)

再帰的な文字列連結を使用してHTMLテーブル本体を作成しようとしています。ブランド順に並べた店舗ごとの売上を表示する必要があります。同じブランドの店舗の各グループの後に、次のようにそのブランドの売上の小計を表示します。

ここに画像の説明を入力してください

私はそれを次のようにしています:

DECLARE @tableBody NVARCHAR(MAX), @lastBrand VARCHAR(10);
SELECT @tableBody='';

SELECT
  @tableBody
    = @tableBody
      + CASE
          WHEN @lastBrand IS NOT NULL AND @lastBrand<>SS.Brand
            THEN '<tr><td colspan="2">Subtotal</td><td>'
                 + (SELECT TOP 1 CAST(SB.TotalSales AS VARCHAR(15)) FROM #SalesByBrand SB WHERE SB.Brand=@lastBrand)
                 + '</td></tr>'
            ELSE '' END
      + '<tr><td>' + SS.Brand + '</td><td>'
      + SS.StoreName + '</td><td>' + CAST(SS.Sales AS VARCHAR(15)) + '</td></tr>',
  @lastBrand = SS.Brand
FROM #SalesByStore SS
ORDER BY SS.Brand

問題は、@ lastBrandがサブクエリに対してnullのままであるため、ブランドごとの小計金額を取得するサブクエリが常にNULLを返すことです(これが発生する理由の説明については、このスタックオーバーフローの質問を参照してください:再帰文字列内のサブクエリの理由連結は常にNULLを返しますか?)。

SQL Server 2005で小計を使用してHTMLテーブルを作成する別の方法を提案できますか?

ちなみに、データベースメールで送信するには、SQLServerでHTMLテーブルを作成する必要があります。

編集:新しいブランドグループが始まる前に小計行を描画する必要があるため、ケースを連結の終了から開始に移動しました。間違いでごめんなさい。

4

2 に答える 2

3

幸いなことに、サブクエリを結合に置き換えて、値を直接選択するだけです。

DECLARE @tableBody NVARCHAR(MAX), @lastBrand VARCHAR(10), @lastTotal decimal(10,2);
SELECT @tableBody='';

SELECT
  @tableBody
    = @tableBody
      + CASE
          WHEN @lastBrand IS NOT NULL AND @lastBrand<>SS.Brand
            THEN '<tr><td colspan="2">Subtotal</td><td>'
                 + CAST(@lastTotal AS VARCHAR(15)) -- Add the last total
                 + '</td></tr>'
            ELSE '' END
      + '<tr><td>' + SS.Brand + '</td><td>'
      + SS.StoreName + '</td><td>' + CAST(SS.Sales AS VARCHAR(15)) + '</td></tr>',
  @lastBrand = SS.Brand,
  @lastTotal = SB.TotalSales -- Save the last total, too
FROM #SalesByStore SS
    join #SalesByBrand SB on SS.Brand = SB.Brand -- Join to get brand totals
ORDER BY SS.Brand

-- Finally add the last total
SELECT
  @tableBody
    = @tableBody
      + '<tr><td colspan="2">Subtotal</td><td>'
      + CAST(@lastTotal AS VARCHAR(15))
      + '</td></tr>'

あなたは確かに、この HTML テーブルを作成する賢い方法を思いつきました。物事を少し動かし、解決策を一緒にハックしたことに注意してください。

このデータセットでテストしました:

insert into #SalesByStore select 'A', 'Store 1', 1000
insert into #SalesByStore select 'A', 'Store 2', 2000
insert into #SalesByStore select 'B', 'Store 3', 1500
insert into #SalesByStore select 'B', 'Store 4', 2100
insert into #SalesByStore select 'B', 'Store 5', 3100
insert into #SalesByBrand select 'A', 3000
insert into #SalesByBrand select 'B', 6700
于 2012-10-04T16:04:31.507 に答える
2

GROUPING SETS と適切な順序を使用する代替。文字列は、XML PATH を使用して結合されます。

作業中のSQL フィドル フィドル
の一番上のクエリは、クエリの後の変数の内容を示しています。一番下のクエリは、GROUPING SETS が生成するものを示しています。

declare @tablebody nvarchar(max) = '';
select @tablebody = (select 
  case
  when storename is null then
   '<tr><td colspan="2">Subtotal</td>
        <td>'+cast(sum(sales) as varchar(15))+'</td></tr>'
 else
   '<tr><td>'+brand+'</td>
        <td>'+storename+'</td>
        <td>'+cast(sum(sales) as varchar(15))+'</td></tr>'
  end
from salesbystore
group by grouping sets
((brand, storename),(brand))
order by brand, case when storename is null then 1 else 0 end
for xml path (''), root('a'), type
).value('(/a)[1]','nvarchar(max)');
select @tablebody;

グループ化は確かに SQL Server 2008 以降の機能であり、WITH ROLLUP のすべての使用を置き換える必要がありますが、この特定の例は、示されている 2 行を置き換える 3 行を使用して、SQL Server 2005 の WITH ROLLUP に簡単に切り替えることができます。

group by brand, storename  -- group by grouping sets
with rollup                -- ((brand, storename),(brand))
having brand is not null
于 2012-10-04T20:25:44.127 に答える