SQL分组结果,小计和总计

时间:2017-09-13 09:50:23

标签: c# sql sql-server wpf

我正在寻找我完全坚持的SQL帮助。还是比较新的...

这就是我现在正在做的事情:

private void FillSalesGrid()
    {            
        using (SqlConnection con = new SqlConnection(conn))
        {
            sqlBuilder.Append("SELECT FORMAT(date, 'd', 'en-gb') AS Date, saleID AS [Invoice ID], Patient.firstName + ' ' + Patient.lastName AS [Name], description AS Description,  saleType AS [Type of Sale], saleAmount AS [Amount (R)] FROM Sale LEFT JOIN Patient ON Sale.patientIDNumber = Patient.patientIDNumber WHERE 1=1");

            if (!string.IsNullOrEmpty(comboBox_selectSaleType.Text))
            {
                try
                {
                    sqlBuilder.Append(" AND saleType = @saleType");
                    cParameters.Add(new SqlParameter("@saleType", comboBox_selectSaleType.SelectedItem.ToString()));
                }
                catch
                {
                    MessageBox.Show("no results");
                }
                if (comboBox_selectSaleType.Text == "All Sales")
                {
                    sqlBuilder.Remove(sqlBuilder.Length - 25, 25);
                }
            }

            if (!string.IsNullOrEmpty(datePicker_StartDate.Text) || !string.IsNullOrEmpty(datePicker_EndDate.Text))
            {

                if (!string.IsNullOrEmpty(datePicker_StartDate.Text) && string.IsNullOrEmpty(datePicker_EndDate.Text))
                {
                    sqlBuilder.Append(" AND date > @startDate");
                    cParameters.Add(new SqlParameter("@startDate", datePicker_StartDate.Text));

                }
                else if (string.IsNullOrEmpty(datePicker_StartDate.Text) && !string.IsNullOrEmpty(datePicker_EndDate.Text))
                {
                    sqlBuilder.Append(" AND date < @endDate");

                    cParameters.Add(new SqlParameter("@endDate", datePicker_EndDate.Text));
                }
                else
                {
                    sqlBuilder.Append(" AND date BETWEEN @startDate AND @endDate");
                    cParameters.Add(new SqlParameter("@startDate", datePicker_StartDate.Text));
                    cParameters.Add(new SqlParameter("@endDate", datePicker_EndDate.Text));
                }
            }
            if (!string.IsNullOrEmpty(comboBox_select_Item.Text))
            {
                sqlBuilder.Append(" AND Description LIKE @medName + '%'");
                cParameters.Add(new SqlParameter("@medName", comboBox_select_Item.SelectedItem.ToString()));
            }
            if (!string.IsNullOrEmpty(textBox_PatientIDSelect.Text))
            {
                sqlBuilder.Append(" AND Sale.patientIDNumber = @patientID");
                cParameters.Add(new SqlParameter("@patientID", textBox_PatientIDSelect.Text));
            }

            sqlBuilder.Append(" ORDER BY Sale.date");

            SqlCommand cmd = new SqlCommand(sqlBuilder.ToString(), con);
            if (cParameters.Count != 0)
            {
                cmd.Parameters.AddRange(cParameters.ToArray());
            }

            SqlDataAdapter da = new SqlDataAdapter(cmd);
            dt = new DataTable("Sale");
            da.Fill(dt);
            // totalSales(dt);
            sqlBuilder.Clear();
            cParameters.Clear();
            dataGrid_Reports.ItemsSource = dt.DefaultView;
    }

我从Sales表中提取数据以获取销售报表类型功能。我希望改进它,使其更具可读性/意义。如您所见,我正在使用基于用户输入的参数构建SQL语句。这可能不是最好的方法。

这是一个示例,说明结果在表单加载时的外观,显示我的SALES表。

+----------+-------------+-----------+--------------+--------------+--------
|   date   |  Invoice ID |   Name    |  Description |  Sale Type   | Amount 
+--------- +-------------+-----------+--------------+--------------+--------
| 01/02/91 |    1        |   Dean    |   Panado     |  Cash        |  50    
| 02/02/91 |    3        |   Chris   |   Oralox     |  Cash        |  60    
| 03/02/91 |    5        |   Peter   |   Zadin      |  Card        |  99    
| 05/02/91 |    6        |   John    |   Illiadin   |  Medical Aid |  85    
| 08/02/91 |    8        |   Mike    |   Betamine   |  Cash        |  129   
+----------+-------------+-----------+--------------+--------------+--------+

结果将根据输入的日期,输入的患者ID,药品名称或销售类型进行“过滤”。

理想情况下,我想要这样的东西(patientID与他们的名字相关联):

Name      InvoiceID    Date         Description   Type of Sale   Amount              
John Doe       1       01/02/2009      Panado        Cash          50
               3       02/02/2009      Panado        Cash          50
               5       03/02/2009      Disprin    Medical Aid      99

Sub-Total                                                         R199

对于每位患者 - 然后是最后的总计,以总结所有小计。

这里的任何帮助都绝对值得赞赏。谢谢。

1 个答案:

答案 0 :(得分:0)

假设您的table的样本数据如下所示。

date           Invoice_ID   Name     Description     Sale_Type      Amount
---------------------------------------------------------------------------
02.01.1991        1        John       Panado          Cash            50
02.02.1991        3        John       Oralox          Cash            60
02.03.1991        5        John       Zadin           Card            99
02.05.1991        6        John       Illiadin        Medical Aid     85
02.08.1991        8        John       Betamine        Cash            129

并且您需要将所有行与sub-total一起返回,您可以使用下面的rollup函数生成所需的结果。

SELECT CASE
           WHEN (GROUPING(t1.name) = 1) THEN 'Sub-Total'
           ELSE ISNULL(t1.name, 'UNKNOWN')
       END AS Name,
       t1.date,
       t1.invoice_id,
       t1.description,
       t1.sale_type,
       sum(t1.Amount) as Amount
FROM t1
GROUP BY rollup((t1.date,t1.invoice_id,t1.name,t1.description,t1.sale_type));

<强>结果:

Name                  date          invoice_id  description    sale_type      Amount
------------------------------------------------------------------------------------
John          02.01.1991 00:00:00       1         Panado         Cash           50
John          02.02.1991 00:00:00       3         Oralox         Cash           60
John          02.03.1991 00:00:00       5         Zadin          Card           99
John          02.05.1991 00:00:00       6         Illiadin       Medical Aid    85
John          02.08.1991 00:00:00       8         Betamine       Cash           129
Sub-Total                                                                       423

如果您只需要在第一行显示name,则必须将上述查询用作inner query并使用outer query中的其他案例,如下所示。

SELECT CASE
           WHEN row_number() over(partition BY name
                                  ORDER BY name ASC) =1 THEN name
           ELSE NULL
       END, date, invoice_id,
                  description,
                  sale_type,
                  Amount
FROM
  (SELECT CASE
              WHEN (GROUPING(t1.name) = 1) THEN 'Sub-Total'
              ELSE ISNULL(t1.name, 'UNKNOWN')
          END AS Name,
          t1.date,
          t1.invoice_id,
          t1.description,
          t1.sale_type,
          sum(t1.Amount) AS Amount
   FROM t1
   GROUP BY rollup((t1.date,t1.invoice_id,t1.name,t1.description,t1.sale_type)) ) t;

<强>结果:

Name                  date          invoice_id  description    sale_type      Amount
------------------------------------------------------------------------------------
John          02.01.1991 00:00:00       1         Panado         Cash           50
              02.02.1991 00:00:00       3         Oralox         Cash           60
              02.03.1991 00:00:00       5         Zadin          Card           99
              02.05.1991 00:00:00       6         Illiadin       Medical Aid    85
              02.08.1991 00:00:00       8         Betamine       Cash           129
Sub-Total                                                                       423

您可以查看演示 here

希望这会有所帮助: - )。