0

我有 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 报表来显示相同​​的内容。

4

2 回答 2

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;

输出(在这两种情况下):

| 日期 | 模压 | 乔普 | 经典 | 志伟 |
-------------------------------------------------- -
| 5 月 21 日 | 450 | 150 | 300 | 0 |
| 5 月 22 日 | 300 | 150 | 150 | 0 |

这是SQLFiddle演示(适用于两种方法)。

更新在 Sql Server 中,您可以使用STUFFPIVOT使用动态 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演示。

于 2013-06-17T07:35:49.707 回答
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')
于 2013-06-17T09:46:31.640 回答