如何使用动态枢轴c#winform将总计列和行插入datagridview

Posted

技术标签:

【中文标题】如何使用动态枢轴c#winform将总计列和行插入datagridview【英文标题】:How to insert Grand Total column and row into datagridview with dynamic pivot c# winform 【发布时间】:2021-03-20 02:02:06 【问题描述】:

我的表单上有一个 datagridview,我用它来透视数据库中的信息。这是我的查询命令:

DECLARE @Date AS VARCHAR(MAX),
        @query AS VARCHAR(MAX)
        
SELECT 
    @dATE = STUFF((SELECT ',' + QUOTENAME(REPLACE(CONVERT(VARCHAR(10), CREATED, 101), '-', '/')) 
                   FROM repair_data_entry
                   WHERE MONTH(CREATED) = 12
                     AND YEAR(CREATED) = 2020
                   GROUP BY CREATED
                   ORDER BY CREATED
                   FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, '')

SET @query = 'SELECT NAME AS TECH, ' + @Date + ' 
              FROM  
                  (SELECT NAME, CREATED, REP  
                   FROM repair_data_entry) AS S  
              PIVOT  
                  (COUNT(REP)  
                      FOR CREATED IN ('+@Date+')  
                  ) P'
EXECUTE(@query)

SQL Fiddle

这是我尝试获取总计列和行的查询:

DECLARE @Date1 VARCHAR(MAX),
        @Date2 VARCHAR(MAX),
        @GrandTotalCol VARCHAR(MAX),
        @GrandTotalRow VARCHAR(MAX),
        @FinalQuery VARCHAR(MAX)

SELECT @Date1 = STUFF((SELECT ',' + QUOTENAME(REPLACE(CONVERT(VARCHAR(10), CREATED, 101), '-', '/')) 
                       FROM repair_data_entry
                       WHERE MONTH(CREATED) = 12
                         AND YEAR(CREATED) = 2020
                       GROUP BY CREATED
                       ORDER BY CREATED
                       FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, '')
        
SELECT @Date2  = COALESCE (@Date2 + ',[' + @Date1 + ']', '[' + @Date1 + ']')
FROM repair_data_entry 
GROUP BY CREATED
ORDER BY CREATED

SELECT @GrandTotalCol = COALESCE (@GrandTotalCol + 'ISNULL ([' + 
CAST (@Date1 AS VARCHAR) +'],0) + ', 'ISNULL([' + CAST(@Date1 AS VARCHAR)+ '],0) + ')
FROM repair_data_entry
GROUP BY CREATED
ORDER BY CREATED

SET @GrandTotalCol = LEFT (@GrandTotalCol, LEN (@GrandTotalCol)-1)
 
SELECT @GrandTotalRow = COALESCE(@GrandTotalRow + ',ISNULL(SUM([' + 
CAST(@Date1 AS VARCHAR)+']),0)', 'ISNULL(SUM([' + CAST(@Date1 AS VARCHAR)+']),0)')
FROM repair_data_entry
GROUP BY CREATED
ORDER BY CREATED
  
SET @FinalQuery = 'SELECT *, (' + @GrandTotalCol + ') 
AS [Grand Total] INTO  #temp
            FROM
                (SELECT NAME,CREATED,REP
                    FROM  repair_data_entry
                ) A
            PIVOT
                (
                 COUNT(REP)
                 FOR CREATED
                 IN ('  + @date1 +  ')
                ) B
ORDER BY NAME

SELECT * FROM  #temp_MatchesTotal 
UNION ALL
SELECT ''Grand Total'','''',' + @GrandTotalRow + ',  
ISNULL (SUM([Grand Total]),0) FROM  #temp

DROP TABLE  #temp'

EXECUTE(@FinalQuery) 

SQL Fiddle

我不断收到此错误:

关键字“INTO”附近的语法不正确

我不确定该怎么做,但我知道有办法。这是我搜索、搜索和尝试不同事物的最后手段。

这是我的 C# 代码:

DateTime month = DateTime.Today;
DateTime year = DateTime.Today;

using (SqlConnection cn = new SqlConnection(@"connection"))

    cn.Open();

    using (SqlCommand cmdDashboard = new SqlCommand())
    
        cmdDashboard.CommandText = "DECLARE @Date AS VARCHAR(MAX), @query AS VARCHAR(MAX) select @Date = STUFF((SELECT ',' + QUOTENAME(REPLACE(CONVERT(VARCHAR(10), DATE, 101), '-', '/')) FROM repair_data_entry WHERE MONTH(DATE) = '" + month.Month + "' AND YEAR(DATE) = '" + year.Year + "' GROUP BY DATE ORDER BY DATE FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'),1,1,'') set @query = 'SELECT NAME AS TECH, ' + @Date + ' FROM (SELECT NAME, DATE, REPAIR FROM repair_data_entry) AS S PIVOT (COUNT(REPAIR) FOR DATE IN('+@Date+')) P' EXECUTE(@query)";

        SqlDataAdapter dataadapter = new SqlDataAdapter(cmdDashboard);

        DataSet ds = new DataSet();
        cmdDashboard.Connection = cn;

        dataadapter.Fill(ds, "repair_data_entry");

        dataGridView1.DataSource = ds;
        dataGridView1.DataMember = "repair_data_entry";

        dataGridView1.Columns[0].Frozen = true;
        dataGridView1.Rows[0].Frozen = true;

        dataGridView1.Columns[0].DefaultCellStyle.BackColor = SystemColors.Control;

        foreach (DataGridViewColumn column in dataGridView1.Columns)
        
            column.SortMode = DataGridViewColumnSortMode.NotSortable;
        

        dataGridView1.ClearSelection();
        cn.Close();
    

有些东西与小提琴不同,比如日期列和月份和年份。

我不确定这是否是正确的方法。我还在学习 C# 和 SQL。

【问题讨论】:

【参考方案1】:

好的,根据您的查询,这是您需要做的:

DECLARE @Datecolumns VARCHAR(MAX),
        @GrandTotalCol VARCHAR(MAX),
        @FinalQuery VARCHAR(MAX)

SELECT @Datecolumns = STUFF((SELECT ',' + QUOTENAME(REPLACE(CONVERT(VARCHAR(10), CREATED, 101), '-', '/')) 
                       FROM repair_data_entry
                       GROUP BY CREATED
                       ORDER BY CREATED
                       FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 1, '')

set @GrandTotalCol =  @Datecolumns + ',[GrandTotal]'

SET @FinalQuery = 'SELECT *
INTO  #temp
FROM
(
select 
  Name
  ,case when GROUPING(CONVERT(VARCHAR(10), CREATED, 101)) = 1 
      then ''GrandTotal'' 
      else CONVERT(VARCHAR(10), CREATED, 101) end as CREATED
  , COUNT(REP) REP
from repair_data_entry
group by name , ROLLUP (CONVERT(VARCHAR(10), CREATED, 101))
) as source 
            PIVOT
                (
                 SUM(REP)
                 FOR CREATED
                 IN ('  + @GrandTotalCol +  ')
                ) B
ORDER BY NAME

SELECT * FROM  #temp

DROP TABLE  #temp'

EXECUTE(@FinalQuery) 
GO
姓名 | 2020 年 11 月 2 日 | 2020 年 12 月 1 日 | 2020 年 12 月 2 日 |累计 :---- | ---------: | ---------: | ---------: | ---------: 比尔 | | 6 | 5 | 11 账单2 | 1 | 3 | 3 | 7

db小提琴here

【讨论】:

我正在使用 sql server 2014。我希望它看起来像一个带有总计列和总计行的 excel 数据透视表。不过,这项工作非常完美!谢谢!我理解它,我可以看到它在做什么。当我尝试添加总计行时,我将该行作为一列。 db fiddle。这是我试图得到它的方法:image【参考方案2】:

下面这两行看起来根本不正确,特别是当您尝试使用 sum() 函数准备 @GrandTotalRow 时

SELECT @GrandTotalCol = COALESCE (@GrandTotalCol + 'ISNULL ([' + 
CAST (@Date1 AS VARCHAR) +'],0) + ', 'ISNULL([' + CAST(@Date1 AS VARCHAR)+ '],0) + ')
FROM repair_data_entry
GROUP BY CREATED
ORDER BY CREATED

SET @GrandTotalCol = LEFT (@GrandTotalCol, LEN (@GrandTotalCol)-1)
 
SELECT @GrandTotalRow = COALESCE(@GrandTotalRow + ',ISNULL(SUM([' + 
CAST(@Date1 AS VARCHAR)+']),0)', 'ISNULL(SUM([' + CAST(@Date1 AS VARCHAR)+']),0)')
FROM repair_data_entry
GROUP BY CREATED
ORDER BY CREATED

这里是输出打印@GrandTotalCol:

ISNULL([[12/01/2020],[12/02/2020]],0) + ISNULL ([[12/01/2020],[12/02/2020]],0) + 

并打印@GrandTotalRow:

ISNULL(SUM([[12/01/2020],[12/02/2020]]),0),ISNULL(SUM([[12/01/2020],[12/02/2020]]),0)

它们都没有产生有效的 sql 语法:

ISNULL( 只需要 2 个参数 SUM() 只接受 1 个参数 不平衡 [[ 和 ]]

相反,我建议您更多地研究GROUP BY ROLLUP 命令,它可能对您正在尝试做的事情有所帮助。

【讨论】:

我不知道谁把你的解释标记为无用。我发现它很有用,因为我仍在学习所有这些。感谢您指出正确的方向!不过仍在寻找具体的方向。 @Bill 不客气,粘贴您想要的输出,这样我们可以更好地帮助您,如果有帮助,您可以投票,谢谢 @Bill 你用的是哪个版本的sql?

以上是关于如何使用动态枢轴c#winform将总计列和行插入datagridview的主要内容,如果未能解决你的问题,请参考以下文章

带有枢轴的存储过程不会返回结果结构而是返回零值

Pandas:DataFrame数据的更改插入新增的列和行

ActionScript 3 动态列和行

如何将数据从 python 列表中的列和行写入 csv 文件?

如何将列和行设置为 tkinter 框架中的窗口大小?

以编程方式将列和行添加到 WPF Datagrid