MS Chart control - Optimize method for displaying 'zero' Y value columns for a Line chart type
I’m using Microsoft Chart extensions that ship with VS 2010. This suits my needs well, but I’ve run into an annoyance and am looking for a more elegant solution.
When charting a line graph, to achieve a continuous line, I require data for all X coordinates. My dataset is for number of sales by employee by month, where sales count is on the Y and month is on the X. The problem arises where no data is returned for an X value (ie. An employee took a month off)…so the line is n开发者_运维问答ot continuous.
I’m not sure if there is a setting I’ve overlooked in the Chart control, but my inelegant solution is to create ‘fake’ zero sales data for the months the employee posted no sales.
I’m using a stored procedure in MS SQL to create my dataset, where each column is a month and each row is for an employee. I create a new series in the Chart control for each employee then.
In order to capture my zero sales months, I have created a temp table in SQL.
CREATE TABLE @tblMonth (myMonth nvarchar(10), defaultCount int)
INSERT INTO @tblMonth VALUES (‘January’, 0)
…
INSERT INTO @tblMonth VALUES (‘December’, 0)
I then perform a join of my temp table on my actual data record and use
ISNULL (realData.Count, tblMonth.defaultCount)
To get my ‘fake’ zero sales data.
This works…but FEELS really kludgy to me…I can’t help but feel I’ve overlooked something simple that would better suit my purposes. Again, I’ve got this working…but always looking for better ways of doing things and expand my knowledge base….so if anyone has suggestions of how better to accomplish the above, I’d love some suggestions or feedback.
If tblMonth.DefaultCount will always be zero, then why not:
ISNULL (realData.Count, 0)
Here's what I am guessing your query looks like:
SELECT
sales_month = DATENAME ( month, s.sale_date )
, sales_month_n = DATEPART( month, s.sale_date)
, salesperson = e.employee_name
, numb_of_sales = COUNT ( 1 )
FROM
sales s
JOIN employee e
ON s.employee_id_salesperson = e.employee_id
WHERE s.sale_date >= '1/1/2010' and s.sale_date < '1/1/2011'
GROUP BY
DATENAME ( month, s.sale_date ), e.employee_name, DATEPART( month, s.sale_date)
--which works fine, until you have an employee take off in June, July and August. You still want them to show up in the resultset, but with zero sales
CREATE TABLE @tblMonth (myMonth nvarchar(10), n tinyint)
INSERT INTO @tblMonth VALUES ('January', 1)
...
INSERT INTO @tblMonth VALUES ('December', 12)
SELECT
all_possibles.sales_month
, all_possibles.salesperson
, ISNULL ( actual.numb_of_sales, 0 )
FROM
(
SELECT
sales_month = myMonth
, sales_month_n = n
, salesperson = e.employee_name
FROM
employee e
,@tblMonth M
)all_possibles
LEFT JOIN
(
SELECT
sales_month_n = DATEPART( month, s.sale_date)
, salesperson = e.employee_name
, numb_of_sales = COUNT ( 1 )
FROM
sales s
JOIN employee e
ON s.employee_id_salesperson = e.employee_id
WHERE s.sale_date >= '1/1/2010' and s.sale_date < '1/1/2011'
GROUP BY
e.employee_name, DATEPART( month, s.sale_date)
)actuals
ON
(
all_possibles.salesperson = actuals.salesperson
AND all_possibles.sales_month_n = actuals.sales_month_n
)
Sorry for the long winded answer. Hope you feel reassured that you are on the right track. Good luck!
As to kludgy - instead of @tblMonth, I use permanent tables in a utility / resource database. it is already populated with things like a record for every minute in the day, or in this case, a record for every month in a year. These types of tables, forget what they are called - maybe a form of fact table? are VERY useful when looking for or filling in gaps in data.
精彩评论