我有2张桌子。它们如下
表:等级
GradeID | Grade
-----------------
1 | Chopsaw
2 | Classic
3 | Chieve
表:模塑量
Batch ID | Grade | Moulded | Date
-------------------------------------
1 | 1 | 150 | 21st May
2 | 1 | 150 | 22nd May
3 | 2 | 150 | 21st May
4 | 2 | 150 | 21st May
5 | 2 | 150 | 22nd May
我应该像以下
那样得到输出Date | Moulded | Chopsaw | Classic | Cieve
--------------------------------------------------
21st May | 450 | 150 | 300 | 0
22nd May | 300 | 150 | 150 | 0
我正在使用MSSQL 2008,我使用Crystal报表来显示相同的内容。
答案 0 :(得分:3)
如果事先知道成绩数,那么您可以使用静态查询来完成。
SELECT date,
SUM(moulded) moulded,
SUM(CASE WHEN grade = 1 THEN moulded ELSE 0 END) Chopsaw,
SUM(CASE WHEN grade = 2 THEN moulded ELSE 0 END) Classic,
SUM(CASE WHEN grade = 3 THEN moulded ELSE 0 END) Chieve
FROM moulded_quantity
GROUP BY date
此查询不是特定于供应商的,因此它应该适用于任何主要的RDBMS。
现在,如果成绩数量未知或者您希望它能够工作,即使您对grade
表进行了更改(不更改查询本身),也可以使用动态查询。但动态SQL是特定于供应商的。以下是如何在MySql中执行此操作的示例
SELECT CONCAT (
'SELECT date, SUM(moulded) moulded,',
GROUP_CONCAT(DISTINCT
CONCAT('SUM(CASE WHEN grade = ',gradeid,
' THEN moulded ELSE 0 END) ', grade)),
' FROM moulded_quantity GROUP BY date') INTO @sql
FROM grade;
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
输出(在两种情况下):
| DATE | MOULDED | CHOPSAW | CLASSIC | CHIEVE | --------------------------------------------------- | 21st May | 450 | 150 | 300 | 0 | | 22nd May | 300 | 150 | 150 | 0 |
以下是 SQLFiddle 演示(针对这两种方法)。
UPDATE 在Sql Server中,您可以使用STUFF
和PIVOT
通过动态sql生成预期结果
DECLARE @colx NVARCHAR(MAX), @colp NVARCHAR(MAX), @sql NVARCHAR(MAX)
SET @colx = STUFF((SELECT ', ISNULL(' + QUOTENAME(Grade) + ',0) ' + QUOTENAME(Grade)
FROM grade
ORDER BY GradeID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET @colp = STUFF((SELECT DISTINCT ',' + QUOTENAME(Grade)
FROM grade
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET @sql = 'SELECT date, total moulded, ' + @colx +
' FROM
(
SELECT date, g.grade gradename, moulded,
SUM(moulded) OVER (PARTITION BY date) total
FROM moulded_quantity q JOIN grade g
ON q.grade = g.gradeid
) x
PIVOT
(
SUM(moulded) FOR gradename IN (' + @colp + ')
) p
ORDER BY date'
EXECUTE(@sql)
输出与MySql案例相同。
这是 SQLFiddle 演示。
答案 1 :(得分:0)
我建议你先问问题研究,因为这是非常常见的问题。
<强>更新强>
DECLARE @COLUMNS varchar(max)
SELECT @COLUMNS = COALESCE(@COLUMNS+'],[' ,'') + CAST(Grade as varchar)
FROM Grade
GROUP BY Grade
SET @COLUMNS = '[' + @COLUMNS + ']'
DECLARE @COLUMNS_WITH_NULL varchar(max)
SELECT @COLUMNS_WITH_NULL = COALESCE(@COLUMNS_WITH_NULL+',ISNULL([' ,'ISNULL([') + CAST(Grade as varchar) + '], 0) AS ' + CAST(Grade as varchar)
FROM Grade
GROUP BY Grade
DECLARE @COLUMNS_SUMS varchar(max)
SELECT @COLUMNS_SUMS = COALESCE(@COLUMNS_SUMS+' + ISNULL([' ,'ISNULL([') + CAST(Grade as varchar) + '], 0) '
FROM Grade
GROUP BY Grade
SET @COLUMNS_SUMS = '(' + @COLUMNS_SUMS + ') as Moulded'
PRINT @COLUMNS_SUMS
EXECUTE (
'
SELECT
Date, ' + @COLUMNS_SUMS + ', ' + @COLUMNS_WITH_NULL + '
FROM (
SELECT
m.Moulded,
m.date AS Date,
g.Grade
FROM Grade g
INNER JOIN [Moulded Quantity] m
ON m.GRADE = g.GradeID
) up
PIVOT (SUM(Moulded) FOR Grade IN ('+ @COLUMNS +')) AS pvt')