5

UTENSILS次のような3列のテーブルがあります。

CLASS_NAME   RANGE    COUNT
---------------------------
pens         0-0.5     200
pencil       0-0.5      50
pens         0.5-1.0   300 
pencil       0.5-1.0    40
pens         1.0-1.5   150
pencil       1.0-1.5    45 

上記の表の結果を次のように表示するクエリが必要です。

RANGE      Pens        Pencils
------------------------------
0-0.5       200          50
0.5-1.0     300          40
1.0-1.5     150          45

これについてのアイデアはありますか?前もって感謝します!

4

3 に答える 3

3

あなたがやろうとしていることは、 として知られていPIVOTます。これは、データを行から列に変換するときです。一部のデータベースにはPIVOT利用できる機能がありますが、どの RDBMS を指定していません。

関数がない場合は、集計関数とステートメントPIVOTを使用して機能を複製できます。CASE

select `range`,
  sum(case when class_name = 'pens' then `count` end) pens,
  sum(case when class_name = 'pencil' then `count` end) pencils
from yourtable
group by `range`

デモで SQL Fiddle を参照してください

注: バッククォートは MySQL 用です。SQL Server の場合は、 と を角括弧で囲みrangeますcount。これらは、予約語をエスケープするために使用されます。

関数を持つ RDBMS で作業している場合はPIVOT、次を使用できます。

select *
from
(
  select class_name, [range], [count]
  from yourtable
) src
pivot
(
  sum([count])
  for class_name in ([pens], [pencil])
) piv

デモで SQL Fiddle を参照してください

どちらも同じ結果になります。

|   RANGE | PENS | PENCIL |
---------------------------
|   0-0.5 |  200 |     50 |
| 0.5-1.0 |  300 |     40 |
| 1.0-1.5 |  150 |     45 |

の値の既知の数がある場合、上記はうまく機能class_nameします。そうでない場合、RDBMS によっては、このクエリの動的バージョンを生成する方法があります。

SQL Server では、動的バージョンは次のようになります。

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(CLASS_NAME) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT [range], ' + @cols + ' from 
             (
                select CLASS_NAME, [RANGE], [COUNT]
                from yourtable
            ) x
            pivot 
            (
                sum([COUNT])
                for CLASS_NAME in (' + @cols + ')
            ) p '

execute(@query)

デモで SQL Fiddle を参照してください

于 2012-11-30T11:04:20.627 に答える
0

ピボットの動的バージョンは次のとおりです。

IF OBJECT_ID('tempdb..#T') IS NOT NULL
    DROP TABLE #T

CREATE TABLE #T(
    [CLASS_NAME] VARCHAR(20) NOT NULL
    , [range] VARCHAR(10) NOT NULL
    , [count] INT NOT NULL
)

INSERT INTO #T([CLASS_NAME], [range], [count]) VALUES ('pens', '0-0.5', '200')
INSERT INTO #T([CLASS_NAME], [range], [count]) VALUES ('pencil', '0-0.5', '50')
INSERT INTO #T([CLASS_NAME], [range], [count]) VALUES ('pens', '0.5-1.0', '300')
INSERT INTO #T([CLASS_NAME], [range], [count]) VALUES ('pencil', '0.5-1.0', '40')
INSERT INTO #T([CLASS_NAME], [range], [count]) VALUES ('pens', '1.0-1.5', '150')
INSERT INTO #T([CLASS_NAME], [range], [count]) VALUES ('pencil', '1.0-1.5', '45')

DECLARE @PivotColumnHeaders VARCHAR(MAX)

SELECT  @PivotColumnHeaders = STUFF((
        --SELECT DISTINCT TOP 100 PERCENT
        SELECT DISTINCT '],[' + [CLASS_NAME]
        FROM #T
        ORDER BY '],[' + [CLASS_NAME]
        FOR XML PATH('')
    ), 1, 2, '') + ']';

DECLARE @PivotTableSQL NVARCHAR(MAX)
SET @PivotTableSQL = N'
  SELECT *
  FROM (
    SELECT *
    FROM #T
  ) AS PivotData
  PIVOT (
    SUM([count])
    FOR [CLASS_NAME] IN (
      ' + @PivotColumnHeaders + '
    )
  ) AS PivotTable
'

EXECUTE(@PivotTableSQL)
于 2012-11-30T11:19:54.400 に答える
0

このピボット クエリは、すべての主要な DBMS で使用できます。トリックは、不正な列名の「範囲」および「カウント」引用符付きプロパティを取得することです。

SQL Server (以下) は を使用し[]、MySQL はバックティック (`) を使用し、Oracle は二重引用符を使用し、SQLite は前述のいずれかを使用できます。

  select [range],
         sum(case when class_name='pens' then [count] else 0 end) Pens,
         sum(case when class_name='pencil' then [count] else 0 end) Pencils
    from tbl
group by [range]
order by [range];
于 2012-11-30T11:05:03.497 に答える