我正在创建一个case语句(在视图中),它测试2个变量并输出另一个字段的值。它测试的2个变量是ForecastMultiplier和一个获取当前周数的函数。预测乘数表示需要多少个月才能生效。然后,我有一个有12个月预测的表格,我用它来计算我们应该有多少手头库存。
以下是一些例子:
并且还需要对.5,1.5等的预测乘数进行此操作。所以你可以看到,使用一个简单的选择案例会变得非常麻烦。
以下是一些案例陈述,您可以看到:
CASE
when mpi.UseForecast = 0 then mpi.MinimumOnHandQuantity
when mpi.ForecastMultiplier = 1 and dbo.GetWeekNumber() = 1 Then fp.month1
when mpi.ForecastMultiplier = 1 and dbo.GetWeekNumber() = 2 Then (fp.month1 * .75) + (fp.MONTH2 * .25)
when mpi.ForecastMultiplier = 1 and dbo.GetWeekNumber() = 3 Then (fp.month1 * .50) + (fp.MONTH2 * .50)
when mpi.ForecastMultiplier = 1 and dbo.GetWeekNumber() = 4 Then (fp.month1 * .25) + (fp.MONTH2 * .75)
when mpi.ForecastMultiplier = 1.5 and dbo.GetWeekNumber() = 1 Then fp.month1 + (fp.month2 * .5)
when mpi.ForecastMultiplier = 1.5 and dbo.GetWeekNumber() = 2 Then (fp.month1 * .75) + (fp.month2 * .5)
when mpi.ForecastMultiplier = 1.5 and dbo.GetWeekNumber() = 3 Then (fp.month1 * .50) + (fp.month2 * .5)
when mpi.ForecastMultiplier = 1.5 and dbo.GetWeekNumber() = 4 Then (fp.month1 * .25) + (fp.month2 * .5)
when mpi.ForecastMultiplier = 2 and dbo.GetWeekNumber() = 1 Then fp.month1 + fp.month2
when mpi.ForecastMultiplier = 2 and dbo.GetWeekNumber() = 2 Then (fp.month1 * .75) + fp.month2 + (fp.MONTH3 * .25)
when mpi.ForecastMultiplier = 2 and dbo.GetWeekNumber() = 3 Then (fp.month1 * .50) + fp.month2 + (fp.MONTH3 * .50)
when mpi.ForecastMultiplier = 2 and dbo.GetWeekNumber() = 4 Then (fp.month1 * .25) + fp.month2 + (fp.MONTH3 * .75)
SQL语句有效但有一些问题。这很麻烦。我添加的月数越来越慢(它永远不会超过12个月)。此外,它还不需要花费5周的时间来计算。最后,如果可能的话,我们宁愿滚动天,但通过这种方法几乎是不可能的。有没有办法通过存储过程和/或函数执行此操作?顺便说一句,我最初是在Scaler函数中执行select语句,但它非常慢,所以现在我正在尝试查看。
我正在寻找的是一种更好的方法来实现同样的结果,或者我在上一段中提到的更好的结果。
这是Schema和一些数据:
MinimumProductInfoes(MPI):
Code Region UseForecast ForecastMultipler MinimumOnHand
---- ------ ----------- ----------------- -------------
1 R1 0 0 50
1 R2 1 2 0
2 R1 1 4.5 0
2 R3 1 3 0
3 R1 1 12 0
ForecastPivot(FP):
Code Region Month1 Month2 Month3 Month4 Month5 Month6 Month7 ... Month12
---- ------ ------ ------ ------ ------ ------ ------ ------ -------
1 R1 200 200 50 75 200 50 50 80
1 R2 500 500 500 500 500 500 500 500
2 R1 1000 0 0 0 0 0 0 0
2 R3 25 1000 1000 1000 1000 1000 1000 1000
答案 0 :(得分:0)
如果您将一个乘数组合的案例合并为:
,您的陈述可能会变得不那么麻烦,缩短了近4倍。var errors = ko.validation.group(self.personalViewModel, { deep: true });
if (fieldHidden()) {
errors()[0] = "New error message";
}
errors.showAllMessages();
不知何故,我认为这仍然适用于第5周。
答案 1 :(得分:0)
架构设置:(SQLFiddle使用MS SQL 2014,但这在2008年仍然可以使用。)
CREATE TABLE MPI ( Code int, Region varchar(5), UseForecast bit
, ForecastMultiplier decimal(5,1), MinimumOnHand int ) ;
INSERT INTO MPI ( Code, Region, UseForecast, ForecastMultiplier, MinimumOnHand )
VALUES
( 1,'R1',0,0,50 )
, ( 1,'R2',1,2,0)
, ( 2,'R1',1,4.5,0)
, ( 2,'R3',1,3,0)
, ( 3,'R1',1,12,0)
;
CREATE TABLE FP ( Code int, Region varchar(5), Month1 int, Month2 int
, Month3 int, Month4 int, Month5 int, Month6 int, Month7 int
, Month8 int, Month9 int, Month10 int, Month11 int, Month12 int ) ;
INSERT INTO FP (Code, Region, Month1, Month2, Month3, Month4, Month5
, Month6, Month7, Month8, Month9, Month10, Month11, Month12 )
VALUES
( 1,'R1',200,200,50,75,200,50,50,50,50,50,50,80 )
, ( 1,'R2',500,500,500,500,500,500,500,50,50,50,50,500 )
, ( 2,'R1',1000,0,0,0,0,0,0,50,50,50,50,0 )
, ( 2,'R3',25,1000,1000,1000,1000,1000,1000,50,50,50,50,1000 )
;
构建简单日历表:
注意:日历表适用于您的数据库,因此请添加您需要的任何计算。我经常使用Aaron Bertrand的修改版本的例子:https://github.com/shawnoden/SQL_Stuff/blob/master/sql_CreateDateDimension.sql
/* #dim is just a temp holding table for intermediate calculations. */
CREATE TABLE #dim (
theDate date PRIMARY KEY
, theDay AS DATEPART(day, theDate) --int
, theWeek AS DATEPART(week, theDate) --int
, theMonth AS DATEPART(month, theDate) --int
, theYear AS DATEPART(year, theDate) --int
, yyyymmdd AS CONVERT(char(8), theDate, 112) /* yyyymmdd */
, mm_dd_yy AS CONVERT(char(10), theDate, 101) /* mm/dd/yyyy */
);
/**************************************************************************/
/* Use the catalog views to generate as many rows as we need. */
INSERT INTO #dim ( theDate )
SELECT d
FROM (
SELECT d = DATEADD(day, rn - 1, '20170101')
FROM
(
SELECT TOP (DATEDIFF(day, '20160101', '20190101'))
rn = ROW_NUMBER() OVER (ORDER BY s1.object_id)
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
ORDER BY s1.object_id
) AS x
) AS y;
/* Now create the final ref table for the dates. */
CREATE TABLE refDateDimension
(
DateKey int NOT NULL PRIMARY KEY
, theDate date NOT NULL
, theDay tinyint NOT NULL
, WeekOfMonth tinyint NOT NULL
, theMonth tinyint NOT NULL
, theYear int NOT NULL
, mm_dd_yy char(10) NOT NULL /* mm/dd/yyyy */
);
/* Insert data in the dimension table. */
INSERT refDateDimension WITH (TABLOCKX)
SELECT
DateKey = CONVERT(int, yyyymmdd)
, theDate = theDate
, theDay = CONVERT(tinyint, theDay)
, WeekOfMonth = CONVERT(tinyint
, DENSE_RANK() OVER
(PARTITION BY theYear, theMonth
ORDER BY theWeek)
)
, theMonth = CONVERT(tinyint, theMonth)
, theYear = theYear
, mm_dd_yy = mm_dd_yy
FROM #dim
OPTION (MAXDOP 1);
/* CLEANUP */
DROP TABLE #dim ;
现在我们使用日历表快速查找周数。:
SELECT s1.Code
, s1.Region
, CEILING(s1.ForecastMinOnHand) AS ForecastMinOnHand /* Round up to even number. */
FROM (
SELECT MPI.Code, MPI.Region
--, MPI.UseForecast, MPI.ForecastMultiplier, d.WeekOfMonth
, CASE
WHEN MPI.UseForecast = 0 THEN MPI.MinimumOnHand
WHEN MPI.ForecastMultiplier = 1 THEN CASE d.WeekOfMonth
WHEN 1 THEN FP.Month1
WHEN 2 THEN (FP.Month1*.75) + (FP.Month2*.25)
WHEN 3 THEN (FP.Month1*.5) + (FP.Month2*.5)
ELSE (FP.Month1*.25) + (FP.Month2*.75)
END
WHEN MPI.ForecastMultiplier = 2 THEN CASE d.WeekOfMonth
WHEN 1 THEN FP.Month1 + FP.Month2
WHEN 2 THEN (FP.Month1*.75) + FP.Month2 + (FP.Month3*.25)
WHEN 3 THEN (FP.Month1*.5) + FP.Month2 + (FP.Month3*.5)
ELSE (FP.Month1*.25) + FP.Month2 + (FP.Month3*.75)
END
WHEN MPI.ForecastMultiplier = 3 THEN CASE d.WeekOfMonth
WHEN 1 THEN FP.Month1 + FP.Month2 + FP.Month3
WHEN 2 THEN (FP.Month1*.75) + FP.Month2 + FP.Month3 + (FP.Month4*.25)
WHEN 3 THEN (FP.Month1*.5) + FP.Month2 + FP.Month3 + (FP.Month4*.5)
ELSE (FP.Month1*.25) + FP.Month2 + FP.Month3 + (FP.Month4*.75)
END
WHEN MPI.ForecastMultiplier = 4.5 THEN CASE d.WeekOfMonth
WHEN 1 THEN FP.month1 + fp.month2 + fp.month3 + fp.month4 + (FP.month5*.5)
WHEN 2 THEN (FP.Month1*.75) + fp.month2 + fp.month3 + fp.month4 + (FP.Month5*.75)
WHEN 3 THEN (FP.Month1*.5) + fp.month2 + fp.month3 + fp.month4 + FP.Month5
ELSE (FP.Month1*.25) + fp.month2 + fp.month3 + fp.month4 + FP.Month5 + (FP.Month6*.25)
END
END AS ForecastMinOnHand
--, MPI.*, FP.*
FROM MPI
INNER JOIN refDateDimension d ON CAST(getDate() AS date) = d.theDate
INNER JOIN FP ON MPI.Code = FP.Code
AND MPI.Region = FP.Region
) s1
<强> Results 强>:
| Code | Region | ForecastMinOnHand |
|------|--------|-------------------|
| 1 | R1 | 50 |
| 1 | R2 | 1000 |
| 2 | R1 | 750 |
| 2 | R3 | 2269 |
我在这里使用日历表的主要目的是它取消了GetWeekNumber()
功能并节省了大量处理周期。它还可以让您的SQL优化器更高效地运行。通常,您可以向其添加更多列,以计算您在其他地方需要的时间计算。这是一个实用工具表。 非常方便。
我仍然认为长CASE
语句可以稍微提炼一下。如果您能够编辑ForecastPivot
视图,那么您应该能够在没有支点的情况下更轻松地获取这些数据。