我有以下要求
Sales Officer: Bob
Week1 Week2 Week3 ................. Week52
Prod1 10 15 12 ................. 14
Prod2 20 14 10 ................. 17
. .
. .
. .销售主管每周为每位销售人员设定目标。销售员可以根据设定的目标,通过类似的网格,每天输入每种产品的实际销售。
编辑
在上述情况下,主管已经为第一周设定了10个单元的目标,现在销售官将以1,2,0,1,3,2=9(第一周实际销售)的方式进入销售,因此,在第一周他已经卖出了9个单元。
我已经创建了“员工”和“产品”表。关于如何在存储目标的数据库中存储、days、和weeks、和实际销售的最佳实践,可以提供任何一个指南吗?
我正在考虑在下表中存储数据
EmpSales (EmployeeID,ProductID,SaleTarget,Actual Sale,Date,WeekNo,Month)提前感谢
发布于 2010-12-10 13:03:11
就我个人而言,我会选择一个更通用的“期间”表。
期间(periodId,startDate,endDate,weekNo,月份,年份)
然后添加
empSales(EmployeeId,ProductId,SaleTarget,ActualSale,periodId)。
这有点灵活(您可以很容易地引入不同的时间跨度,或者使相对周字段为空,或者定义一些规则来映射“标准”周上的周期),这样就减少了冗余(注意月份和周是如何从empSales表中移开的),它允许您进行报告和计算(顺便说一下,您没有包含一个年份字段,有原因吗?)
总结内容应该更容易,因为假设您有按日排序的销售额,除非您想在DB中复制"week“字段,否则在间隔之间对这些内容进行汇总比较容易。
还请注意,您可以很容易地在不同的重叠期上设置目标。
例如,您可以为11月22日至28日的周设定一个每周的目标(我正在使用欧洲大会的一周从星期一开始),并在黑色星期五设定一个特殊的一天周期。
所以:
Period:
periodId|startDate |endDate |weekNo|Month | Year|
0030020|22-NOV-2010|28-NOV-2010| 43 |November | 2010 |
0030026|26-NOV-2010|26-NOV-2010| null |November | 2010 |
empSales:
EmployeeId|ProductId|SaleTarget|ActualSale|periodId|
567689| 788585| 58 | 42 | 0030020|
567689| 788585| 28 | 32 | 0030026|请注意,567689员工是如何错过了每周的目标,但却成功地超过了他的黑色星期五目标。
顺便说一下,在处理这个示例时,我认为最好删除"empSales“表,将其重命名为"empTargets":
empTargets(EmployeeId,ProductId,SaleTarget,periodId)。
因为实际的销售额很容易通过UDF或者放在视图中实时计算--毕竟,它只是一个
select sum(items_sold)
from sales
where sales.employeeId = empTargets.employeeId and
sales.ProductId= empTargets.ProductId and
sales.saleDate between empTargets.startDate and
empTargets.endDate)因此,不需要直接将其存储在表中(事实上,在返回项目或其他今后更正的情况下,它可能成为负担)。
发布于 2010-12-13 08:55:59
在纯关系建模术语中,这是非常容易的。我不认为有必要进行任何形式的“去分化”。
。
如果您不熟悉关系数据库建模标准,可能会有所帮助。
纯5NF;完全声明引用完整性;没有full,没有更新异常;没有GROUP BYs;纯日期算法。
SaleTarget与SaleActual通过投影进行比较,并且可能在相同的结果集中。如果您有月度和年度销售会计,所需的扩展是一个具有一些控制或结构的通用日历表;例如。类似于Week,包括每个月和一年的行。让我知道,我会更新模型,,
我认为这甚至可能是不言自明的,但我将提供动词短语,其中详细说明了业务规则,这只是因为有三个家长参与其中:
F 229完成的
比较
我应该提到的
StartDate 和 EndDate )时,您已经破坏了3NF (引入了函数依赖项),并引入了一个更新异常。任何行中的EndDate,都是下一行中的StartDate (减1秒算作欺骗,是一个设计);在更新时,现在必须更改两行而不是一行。更重要的是,这种结构是如此简单(它不是时间序列或“时间”需求),也不需要EndDate。对评论的答复
Month和Year需求。现在需要对SaleTarget设置一个检查约束,以确保DateType是一周内的W。加载日期表很简单,您不需要发布在SQLTeam上的无意义代码(手动重复剪切粘贴);它们以愚蠢而闻名,SQLTeam SaleActual表现在包含了每日、每周、每月和年度值。当然,您可以在每周、每个月、每一天的第一天进行编程总结。首先,将新行添加到Date.发布于 2010-12-10 14:10:12
我个人会将目标和实际值分别存储在不同的行中,并且很可能存储在单独的表中:
目标: EmployeeId,PeriodId,ProductId,TargetValue
销售: EmployeeId,PeriodId,ProductId,SalesValue
事实上,在集成系统中,第二个表通常是不必要的(假设您有一个完整的销售记录系统,这应该是对实际记录的销售的预测/视图-根据该子系统的模型适当分配员工、期间和产品)。
为了满足您的日历要求,我几乎肯定会有一个日期表,该表将允许您确保所有用于定义周和月的业务规则,而不需要复杂的日期逻辑。然后,通过与日历表的联接,可以方便地确定周期和聚合。
因此,ActualSales看起来应该是这样的(只有一个泛型句点表,它本身可能是一个句号和日期表):
SELECT sp.EmployeeId
, p.ProductId
, pd.PeriodType
, pd.PeriodId
, SUM(id.Quantity * id.UnitProce) AS TotalSales
FROM Invoice AS i
INNER JOIN InvoiceDetail AS id
ON id.InvoiceId = i.InvoiceId
INNER JOIN Employee AS sp
ON sp.EmployeeId = i.SalesPersonId
INNER JOIN Product AS p
ON id.ProductId = p.ProductId
INNER JOIN Period AS pd
ON pd.StartDate <= i.InvoiceDate
AND pd.EndDate > i.InvoiceDate
GROUP BY sp.EmployeeId, p.ProductId, pd.PeriodType, pd.PeriodId在这种情况下,如果您有重叠的周期(比如日、周、月),数据就会被复制,所以您只需要聚合一种类型的周期--这就是为什么我在这个示例视图中专门包含了它,尽管它在这里是多余的。
我预计通用期间表将类似于:
PeriodId
PeriodType
StartDate
EndDate这将预先填充要报告的各个时间段:
'Q', 1/1/2010, 4/1/2010
'M', 1/1/2010, 2/1/2010
'M', 2/1/2010, 3/1/2010
'M', 3/1/2010, 4/1/2010
'W', 1/3/2010, 1/10/2010
'W', 1/10/2010, 1/17/2010
etc.
'D', 1/1/2010, 1/2/2010
'D', 1/2/2010, 1/3/2010
etc.担心假期是没有什么意义的,只是如果他们不工作,你可能不会分配一个目标,这主要是关于管理任务,这样他们大概是现实的。您可以有一个有各种标志的日历表。
Calendar
DateId
Date
IsHoliday然后,当你加入计算一个时期的假期/周末的次数时,你可以把它包括在内。
这通常是会计/业务方面的事情,但您可能需要研究如何标准化您的日历。例如,在媒体购买电视广告时,它们使每个“季度”相等,并使每个“月”标准化--4周、4周、5周。显然,他们对假日和特殊电视事件有例外,但这有助于理顺会计和比较类似时期更容易。
https://stackoverflow.com/questions/4409003
复制相似问题