2

所以我有一个系统,用户可以预测到月底后的第 18 天。但是,在该月中,他们每天都在输入实际值。

所以说当前日期是 2012 年 9 月 12 日。我对这个月有 100 个单位的预测,并且我已经将 25 个单位的实际值输入到系统中。

由于尚未到 10 月 18 日,我将报告 9 月的预测数字为 100 台。但是,用户还希望能够看到他们迄今为止输入的 25 个单位。

我的报告中有两种度量,一种用于实际值,另一种用于预测。如果我允许 9 月的实际数据出现在报告中,那么我将显示 125 个单位的数字,这显然是不正确的,并且会使我的年度总数也不正确。

我考虑添加一个新的度量“Transient Actuals”,它只会在当月使用并且不会累积,但这似乎很疯狂!

我不认为这些技术真的很重要,但我使用的是 SQL Server 数据库,并且报告是一个 Analysis Services 多维数据集。

当然这一定是一个普遍的问题?


好的 - 我确实有一个架构,但它非常非常复杂,并且报告和数据库表之间有多个层。但是,我可以给您一个简单的 SQL 示例。

--Actuals and Forecast Tables
DECLARE @Actuals TABLE (
    [Month] INT,
    Value NUMERIC(19,2));
DECLARE @Forecast TABLE (
    [Month] INT,
    Value NUMERIC(19,2));

--Pretending we are in Month #3 put in some dummy data
INSERT INTO @Actuals VALUES (1, 100);
INSERT INTO @Actuals VALUES (2, 120);
INSERT INTO @Actuals VALUES (3, 10);
INSERT INTO @Forecast VALUES (1, 90);
INSERT INTO @Forecast VALUES (2, 90);
INSERT INTO @Forecast VALUES (3, 90);

--Calculate the latest actuals period (this would usually be time-based)
DECLARE @LatestActualsPeriod INT = 2;

--Now report the data to the user
SELECT
    [Month],
    'Actuals' AS Source,
    Value
FROM
    @Actuals
WHERE
    [Month] <= @LatestActualsPeriod
UNION ALL
SELECT
    [Month],
    'Forecast',
    Value
FROM
    @Forecast
WHERE
    [Month] > @LatestActualsPeriod;

现在,结果将是一个包含以下数据的表:

Month    Source    Value
1        Actuals   100.00
2        Actuals   120.00
3        Forecast   90.00

那么我应该把第 3 个月的 10.00 实际值放在哪里而不会使总数不正确并且仍然在某处显示同一个月的预测?


好的,多亏了杰里米,我想我有答案了......问题是我的报告中有这样的数据:

Row Labels  Actual   Forecast Total
2012    23.840  18.840  42.680
2012/Jan    3.580   0.000   3.580
2012/Feb    3.520   0.000   3.520
2012/Mar    4.000   0.000   4.000
2012/Apr    3.350   0.000   3.350
2012/May    3.440   0.000   3.440
2012/Jun    3.090   0.000   3.090
2012/Jul    2.860   0.000   2.860
2012/Aug    0.000   4.990   4.990
2012/Sep    0.000   3.500   3.500
2012/Oct    0.000   4.130   4.130
2012/Nov    0.000   2.710   2.710
2012/Dec    0.000   3.510   3.510
Grand Total 23.840  18.840  42.680

这是一个 Analysis Services 多维数据集,因此我无法显示“90 个实际/10 个预测”之类的内容,每个单元格都必须包含一个数字。但是,我有另一个解决方案。如果我添加一个包含两个成员的新维度,我可以使用它来控制显示的内容。

所以新维度将有两个选择,“显示全部”或“显示相关”(我可能需要处理名称)。如果用户选择了“显示全部”成员,那么他们将看到系统保存的任何实际值和预测值。因此,这意味着它们的总数将毫无意义,因为它将包括截至并包括本月在内的几个月的预测和实际值,以及对未来几个月的预测。

但是,如果用户选择“显示相关”成员,那么他们将只能看到尚未完成的月份的实际数据和未来月份的预测(如上所示)。

这意味着每个报告都需要包含这个维度并强制用户选择其中一个成员,否则他们的数字将完全没有意义,因此这不是最优雅的解决方案。

4

1 回答 1

1

我在这里做了一堆假设,但希望这在这里有用。我接受了您的查询,并向您展示了其他一些方法,如果我正确理解问题,我认为这些方法可以帮助您解决以更易于阅读的方式显示数据的问题。

在第一个示例中,我假设您始终将日期设置为月初。如果不是,那么它可能会变得有点棘手,或者您可以使用DATEPART(MONTH, ...它来使其工作类似,就好像您将其存储为INT. 我不是假设每个月都会有一个预测值或实际值。

在第二个示例中,为了方便起见,我假设您只想显示最近一个月的实际值和实际值。然后我假设您想要该月及以后的预测值和实际值(如果有)。我还假设在第二个查询中每个月都有一个预测值。

如果这些假设中的任何一个不正确,则可以进一步修改查询以处理该问题。

--Actuals and Forecast Tables
DECLARE @Actuals TABLE (
    [Month] DATE,
    Value NUMERIC(19,2));
DECLARE @Forecast TABLE (
    [Month] DATE,
    Value NUMERIC(19,2));

INSERT INTO @Actuals VALUES ('20120801', 100);
INSERT INTO @Actuals VALUES ('20120901', 120);
INSERT INTO @Actuals VALUES ('20121001', 10);
INSERT INTO @Forecast VALUES ('20120801', 90);
INSERT INTO @Forecast VALUES ('20120901', 90);
INSERT INTO @Forecast VALUES ('20121001', 90);

INSERT INTO @Actuals VALUES ('20121101', 50);
INSERT INTO @Forecast VALUES ('20121201', 90);
-- If you can't have an actuals record without a forcast record, remove all the ISNULL'ing except the first ISNULL on the [Actual/Forecast] line
-- and change to LEFT JOIN instead of FULL.
SELECT
    SUBSTRING(CONVERT(VARCHAR, ISNULL(F.[Month], A.[Month]), 103), 4, 999) [Report Month]
    , ISNULL(CAST(A.Value AS VARCHAR(20)), '-') + '/' + ISNULL(CAST(F.Value AS VARCHAR(20)), '-') [Actual/Forecast]
FROM
    @Forecast F
    FULL JOIN @Actuals A
        ON A.[Month] = F.[Month]
ORDER BY
    [Report Month]

DELETE @Actuals
WHERE [Month] = '20121101'
DELETE @Forecast
WHERE [Month] = '20121201'

DECLARE @LatestActualsPeriod DATE = (SELECT MAX([Month]) FROM @Actuals);

SELECT
    [Month] [Report Month]
    , CAST(A.Value AS VARCHAR(20)) + ' Actual' [Units]
FROM
    @Actuals A
WHERE
    A.[Month] < @LatestActualsPeriod

UNION

SELECT
    F.[Month] [Report Month]
    , ISNULL(CAST(A.Value AS VARCHAR(20)), '-') + '/' + CAST(F.Value AS VARCHAR(20)) + ' Actual/Forecasted'
FROM
    @Forecast F
    LEFT JOIN @Actuals A
        ON A.[Month] = F.[Month]
WHERE
    F.[Month] >= @LatestActualsPeriod

PS:您在答案中添加了架构,但没有回复我要求的评论。如果我没有出于好奇再次回顾这个问题,我就不会知道你编辑了你的问题。

于 2012-09-12T18:48:14.180 回答