SQL 将日期时间作为具有数量字段的列进行透视

SQL Pivot with Datetime as a Column with quantity fields

我在我的数据库上有一个 SQL 视图,用于使用 Lot 和 PartNumberId 打印关于 C# 和 Itext7 的报告以查找结果

DECLARE @LotId int = '1'
DECLARE @PartNumerId int = '100'

SELECT * FROM vw_report_diarydefects WHERE LotId = @LotId AND PartNumerId = @PartNumerId
很多 零件编号 部件号 缺陷编号 缺陷 数量 排序日期
1 100 WD40 1 坏了 9 2019-10-01 10:31:02.000
1 100 WD40 2 油漆划痕 10 2019-10-02 10:31:02.000
1 100 WD40 3 8 2019-10-02 10:31:02.000
1 100 WD40 2 油漆划痕 10 2019-10-03 10:31:02.000
1 100 WD40 4 弯曲 5 2019-10-04 10:31:02.000

我想要做的是将 SortingDate 作为列并在其上添加数量,如下所示:

缺陷 2019-10-01 10:31:02.000 2019-10-02 10:31:02.000 2019-10-03 10:31:02.000 2019-10-04 10:31:02.000
坏了 9 0 0 0
油漆划痕 0 10 10 0
0 8 0 0
弯曲 0 0 0 5

我使用了 pivot(我第一次使用它)并且我已经使用了这个:

DECLARE @StuffColumn varchar(max)
DECLARE @sql varchar(max)

DECLARE @LotId int = '1'
DECLARE @PartNumerId int = '100'

SELECT @StuffColumn = STUFF((SELECT distinct ','+QUOTENAME(SortingDate)
                        FROM vw_report_diarydefects
                                    WHERE LotId = @LotId AND PartNumerId = @PartNumerId
          FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

SET @SQL = ' select Defect, '+ @StuffColumn +'
         from
         (
            select   SortingDate,Defect,Qty
            from vw_report_diarydefects
            where LotId = ''' + CONVERT(NVARCHAR(50), @LotId, 121)+ ''' and PartNumerId = ''' + CONVERT(NVARCHAR(50), @PartNumerId, 121)+ '''
         )x
         pivot
         (
             Sum(Qty)
             for SortingDate in( '+@StuffColumn+' )
         )p'

EXEC(@SQL) 

得到这个:

缺陷 2019 年 10 月 1 日10:31AM 2019 年 10 月 2 日10:31AM 2019 年 10 月 3 日10:31AM 2019 年 10 月 4 日10:31AM
坏了
油漆划痕
弯曲

有没有办法用数量数据填充日期列?我是第一次使用 Pivot,我正在阅读该说明,但我仍有一些疑问。

尝试以下操作:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication193
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Lot",typeof(int));
            dt.Columns.Add("PartNumberId",typeof(int));
            dt.Columns.Add("PartNumber",typeof(string));
            dt.Columns.Add("DefectId",typeof(int));
            dt.Columns.Add("Defect",typeof(string));
            dt.Columns.Add("Qty", typeof(int));
            dt.Columns.Add("SortingDate", typeof(DateTime));

            dt.Rows.Add(new object[] {1, 100, "WD40", 1, "Broken", 9, DateTime.Parse("2019-10-01 10:31:02.000")});
            dt.Rows.Add(new object[] {1, 100, "WD40", 2, "Paint Scratch", 10, DateTime.Parse("2019-10-02 10:31:02.000")});
            dt.Rows.Add(new object[] {1, 100, "WD40", 3, "Swollen", 8, DateTime.Parse("2019-10-02 10:31:02.000")});
            dt.Rows.Add(new object[] {1, 100, "WD40", 2, "Paint Scratch", 10, DateTime.Parse("2019-10-03 10:31:02.000")});
            dt.Rows.Add(new object[] {1, 100, "WD40", 4, "Bent", 5, DateTime.Parse("2019-10-04 10:31:02.000")});


            DateTime[] dates = dt.AsEnumerable().Select(x => x.Field<DateTime>("SortingDate")).OrderBy(x => x).Distinct().ToArray();

            DataTable pivot = new DataTable();
            pivot.Columns.Add("Defect");
            foreach (DateTime date in dates)
            {
                pivot.Columns.Add(date.ToString(), typeof(int));
            }

            foreach(var defect in dt.AsEnumerable().GroupBy(x => x.Field<string>("Defect")))
            {
                DataRow newRow = pivot.Rows.Add();
                newRow["Defect"] = defect.Key;
                foreach (DataRow row in defect)
                {
                    int qty = row.Field<int>("Qty");
                    DateTime date = row.Field<DateTime>("SortingDate");
                    newRow[date.ToString()] = qty;
                }
            }

        }
    }
 
}

这是我的发现。 Quotename 更改日期格式的方式是问题所在。将您的 @StuffColumn 数据更改为先转换为 varchar,然后引用它。

SELECT @StuffColumn = STUFF((SELECT distinct ','+QUOTENAME(CONVERT(NVARCHAR(50),SortingDate, 121))
                        FROM vw_report_diarydefects
                                    WHERE Lot = @LotId AND PartNumberId = @PartNumerId
          FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

这是SQL Fiddle