求C#桌面应用计算当月销售数据的SQL查询或实现逻辑
Alright, let's break down how to solve this—you need to calculate monthly sales, cost, profit, and margin metrics from your Daily_Sale table and display them in a C# desktop app. Here's a straightforward, practical approach:
First, we need a SQL query that groups your daily data by month. Note that your Date_Time field is stored as a string, so we'll first convert it to a proper date type to extract year and month.
Key Notes on Margin Calculation:
- Average Daily Margin: Takes the average of the daily
Marginvalues from your table. - Overall Monthly Margin: Calculates the true margin for the entire month using total profit divided by total sales (this is often more accurate for business reporting).
Pick the one that fits your needs, and comment out the other in the query below:
SELECT -- Creates a first-of-the-month date for sorting DATEFROMPARTS(YEAR(TRY_CONVERT(DATE, Date_Time)), MONTH(TRY_CONVERT(DATE, Date_Time)), 1) AS MonthStart, -- Friendly month name (e.g., "June 2018") DATENAME(MONTH, TRY_CONVERT(DATE, Date_Time)) + ' ' + CAST(YEAR(TRY_CONVERT(DATE, Date_Time)) AS VARCHAR) AS MonthName, SUM(Sale) AS TotalSales, SUM(Cost) AS TotalCost, SUM(Profit) AS TotalProfit, -- Option 1: Average of daily margin values AVG(Margin) AS AverageDailyMargin -- Option 2: Overall monthly margin (uncomment to use) -- (SUM(Profit) / NULLIF(SUM(Sale), 0)) * 100 AS OverallMonthlyMargin FROM Daily_Sale GROUP BY YEAR(TRY_CONVERT(DATE, Date_Time)), MONTH(TRY_CONVERT(DATE, Date_Time)) ORDER BY MonthStart;
If your Date_Time field is already a DATE or DATETIME type (not a string), you can simplify the query by removing all TRY_CONVERT calls—this will make it faster and cleaner.
We'll use ADO.NET here (a common choice for desktop apps) to fetch the data and bind it to a DataGridView for display.
Step 1: Create a Helper Class
This class handles database access and data retrieval:
using System; using System.Data; using System.Data.SqlClient; using System.Windows.Forms; public class MonthlySalesManager { // Replace with your actual database connection string private readonly string _connectionString = "Server=YOUR_SERVER;Database=YOUR_DB;Trusted_Connection=True;"; public DataTable GetMonthlySalesMetrics() { var monthlyData = new DataTable(); var sqlQuery = @" SELECT DATEFROMPARTS(YEAR(TRY_CONVERT(DATE, Date_Time)), MONTH(TRY_CONVERT(DATE, Date_Time)), 1) AS MonthStart, DATENAME(MONTH, TRY_CONVERT(DATE, Date_Time)) + ' ' + CAST(YEAR(TRY_CONVERT(DATE, Date_Time)) AS VARCHAR) AS MonthName, SUM(Sale) AS TotalSales, SUM(Cost) AS TotalCost, SUM(Profit) AS TotalProfit, AVG(Margin) AS AverageDailyMargin -- (SUM(Profit) / NULLIF(SUM(Sale), 0)) * 100 AS OverallMonthlyMargin FROM Daily_Sale GROUP BY YEAR(TRY_CONVERT(DATE, Date_Time)), MONTH(TRY_CONVERT(DATE, Date_Time)) ORDER BY MonthStart; "; try { using (var conn = new SqlConnection(_connectionString)) { using (var cmd = new SqlCommand(sqlQuery, conn)) { conn.Open(); using (var adapter = new SqlDataAdapter(cmd)) { adapter.Fill(monthlyData); } } } } catch (SqlException ex) { MessageBox.Show($"Database error occurred: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (Exception ex) { MessageBox.Show($"Unexpected error: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } return monthlyData; } // Bind the data to a DataGridView for display public void BindDataToGrid(DataGridView dataGridView) { var metricsData = GetMonthlySalesMetrics(); dataGridView.DataSource = metricsData; // Clean up column headers for better readability dataGridView.Columns["MonthStart"].Visible = false; dataGridView.Columns["MonthName"].HeaderText = "Month"; dataGridView.Columns["TotalSales"].HeaderText = "Total Sales"; dataGridView.Columns["TotalCost"].HeaderText = "Total Cost"; dataGridView.Columns["TotalProfit"].HeaderText = "Total Profit"; dataGridView.Columns["AverageDailyMargin"].HeaderText = "Avg Daily Margin (%)"; // If using OverallMonthlyMargin, uncomment this line: // dataGridView.Columns["OverallMonthlyMargin"].HeaderText = "Overall Monthly Margin (%)"; } }
Step 2: Use the Class in Your Form
In your form's load event (or a button click handler), call the helper class to populate the grid:
private void MainForm_Load(object sender, EventArgs e) { var salesManager = new MonthlySalesManager(); salesManager.BindDataToGrid(monthlySalesDataGridView); }
Important Tips:
- Connection String: Make sure to replace
_connectionStringwith your actual database credentials (use integrated security if possible, or addUser IDandPasswordif needed). - Error Handling: The try-catch blocks will catch common issues like database connection failures or invalid data—you can extend this to log errors if needed.
- Performance: If your table has a lot of rows, consider adding an index on the
Date_Timefield (after converting it to a date type) to speed up the grouping.
内容的提问来源于stack exchange,提问作者hamid jalil

