I'm looking for help with SQL that I'm completely stuck with. 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. 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.
+----------+-------------+-----------+--------------+--------------+--------
| 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.
Ideally I want to have something like this (patientID is linked to their name):
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.
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.
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.
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 :-).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.