我有一个表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
有关于此的任何想法?提前谢谢!
答案 0 :(得分: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 Server在range
和count
附近使用方括号,则反引号适用于MySQL。这些用于转义保留字。
如果您正在使用具有PIVOT
功能的RDBMS,那么您可以使用以下内容:
select *
from
(
select class_name, [range], [count]
from yourtable
) src
pivot
(
sum([count])
for class_name in ([pens], [pencil])
) piv
两者都会产生相同的结果:
| 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)
答案 1 :(得分:0)
此透视查询可用于所有主要DBMS。诀窍是将错误的列名称'range'和'count'引用属性。
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];
答案 2 :(得分: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)