简体   繁体   English

SQL分组结果,小计和总计

[英]SQL grouping results, sub-total and grand-total

I'm looking for help with SQL that I'm completely stuck with. 我正在寻找完全坚持的SQL帮助。 Still relatively new... 还是比较新的...

Here's what I'm doing at the moment: 这是我目前正在做的事情:

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;
    }

I'm pulling data from my Sales table for a sales report type functionality. 我正在从“销售”表中提取数据以获取销售报告类型功能。 I'm looking to improve that to make it more readable/meaningful. 我正在寻求改进,使其更具可读性/意义。 As you can see, I'm building the SQL statement with parameters based on input from the user. 如您所见,我正在基于用户输入使用参数构建SQL语句。 This is probably not the best way to do it. 这可能不是最佳方法。

Here's an example of how the results look, on form load, showing my SALES table. 这是一个示例,显示了在表单加载时结果如何显示我的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   
+----------+-------------+-----------+--------------+--------------+--------+

The results will be 'filtered' based on the dates entered, patientID entered, med name or type of sale. 结果将根据输入的日期,输入的患者ID,药品名称或销售类型进行“过滤”。

Ideally I want to have something like this (patientID is linked to their name): 理想情况下,我想要这样的东西(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

For each patient - and then a grand-total at the end to sum up all the sub-totals. 对于每个患者-然后在末尾汇总总计所有小计。

Any assistance here would absolutely be appreciated. 这里的任何帮助将不胜感激。 Thank you. 谢谢。

Assuming from the question that your table have sample data as below. 从问题中假设您的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

and you need to return all rows along with sub-total , you can use rollup function as below to generate your desired result. 并且您需要返回所有行以及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));

Result: 结果:

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

If you just need to show name in first row only, you have to use the above query as inner query and use another case in outer query as below. 如果只需要在第一行中显示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;

Result: 结果:

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

You can check the demo here 您可以在此处查看演示

Hope this will help :-). 希望这会有所帮助:-)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM