[英]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.