我有一个复杂的表,其中显示了销售信息的实际和预测以及多个上载日期。我希望能够在产品ID上加入表,同时查找每个产品的错误百分比,并且仅使用最新信息。这些产品来自众多供应商,因此它们都有不同的名称,但涉及同一产品。例如,来自两个供应商的产品A的名称可能是Supplier1_A和Supplier2_A,但是我希望能够将它们一起添加到一栏中以查找错误。这是数据示例:
Type | ID | DateUpload |Jan. | Feb. | March
Forecast Supplier1_Apples 2018-01-01 5 6 5
Actual Supplier1_Apples 2018-01-01 4 4 5
Forecast Supplier1_Apples 2018-02-01 5 6 5
Actual Supplier1_Apples 2018-02-01 4 6 5
Forecast Supplier2_Apples 2018-02-01 6 6 5
Actual Supplier2_Apples 2018-02-01 4 4 3
Forecast Supplier3_Apples 2018-02-01 8 9 5
Actual Supplier3_Apples 2018-02-01 7 8 5
我最后想要的表看起来像这样
ID | DateUpload | error_jan...
Apples 2018-02-01 (abs(total_actual - total_forecast))/total_actual
此联接是否可以与所有过滤器合并到一个表中?或者我需要创建一个不同的表来获取每个供应商的错误,然后求出平均值吗?目前,我能够基于ID联接表以查找每个ID处的错误,但是在本示例中,如果它们相似以查找苹果的整体错误,则无法将它们全部合并。
答案 0 :(得分:1)
数据准备
declare @mytable as table(
Type varchar(10),
ID varchar(50),
DateUploaded datetime,
JAN decimal
)
insert into @mytable values ('Forecast', 'Supplier1_Apples','2018-01-01',5)
insert into @mytable values ('Actual', 'Supplier1_Apples','2018-01-01',4)
insert into @mytable values ('Forecast', 'Supplier1_Apples','2018-02-01',5)
insert into @mytable values ('Actual', 'Supplier1_Apples','2018-02-01',4)
insert into @mytable values ('Forecast', 'Supplier2_Apples','2018-02-01',6)
insert into @mytable values ('Actual', 'Supplier2_Apples','2018-02-01',4)
insert into @mytable values ('Forecast', 'Supplier3_Apples','2018-02-01',8)
insert into @mytable values ('Actual', 'Supplier3_Apples','2018-02-01',7)
查询:
;With ForecastCTE AS
(
Select
substring(ID, CHARINDEX('_',ID)+1, LEN(ID)) as Id,
DateUploaded,
JAN
From @mytable
Where Type = 'Forecast'
),
ActualCTE AS
(
Select
substring(ID, CHARINDEX('_',ID)+1, LEN(ID)) as Id,
DateUploaded,
JAN
From @mytable
Where Type = 'Actual'
)
Select
F.Id,
F.DateUploaded,
(abs((SUM(A.JAN) - SUM(F.JAN))/SUM(A.JAN))) AS error_jan
from ForecastCTE F
INNER join ActualCTE A on F.ID = A.ID and F.DateUploaded = A.DateUploaded
Group by F.Id,F.DateUploaded
输出:
Id DateUploaded error_jan
Apples 2018-01-01 00:00:00.000 0.250000
Apples 2018-02-01 00:00:00.000 0.266666
答案 1 :(得分:0)
如果要使用固定模式,则可以加入或分组任何产品。例如,在您的示例Supplier1_Apples
中,我们可以看到所有产品Apples
的前缀都带有SupplierID以及(下划线)作为分隔符。供应商名称和产品名称可以更改,但是(下划线)将全部使用。在这种情况下,我们可以使用CHARINDEX()
函数来获取该产品的位置编号(下划线),这将有助于我们仅提取产品ID。
因此,为此,我们将使用CHARINDEX()
,LEN()
和SUBSTRING()
函数具有类似以下内容:
SUBSTRING(ID, CHARINDEX('_',ID,1) + 1,LEN(ID) - CHARINDEX('_',ID,1) + 1)
这将给我们Apples
,这是我们的目标。
从那里,我们可以将GROUP BY
与SUM()
一起使用,将结果分组如下:
SELECT
[Type]
, SUBSTRING(ID, CHARINDEX('_',ID,1) + 1,LEN(ID) - CHARINDEX('_',ID,1) + 1) ID
, DateUpload
, SUM(Jan) Jan
, SUM(Feb) Feb
, SUM(Mar) Mar
FROM test
GROUP BY
[Type]
, SUBSTRING(ID, CHARINDEX('_',ID,1) + 1,LEN(ID) - CHARINDEX('_',ID,1) + 1)
, DateUpload
这将给我们:
| Type | ID | DateUpload | Jan | Feb | Mar |
|----------|--------|------------|-----|-----|-----|
| Actual | Apples | 2018-01-01 | 4 | 4 | 5 |
| Actual | Apples | 2018-02-01 | 15 | 18 | 13 |
| Forecast | Apples | 2018-01-01 | 5 | 6 | 5 |
| Forecast | Apples | 2018-02-01 | 19 | 21 | 15 |
现在,仅将它用作子查询就可以了,您可以从那里走得更远。
一个例子:
SELECT
ID
, DateUpload
, error_jan = ( ABS(TotalJunActual - TotalJunForecast) ) / TotalActual
FROM (
SELECT
ID
, DateUpload
, SUM(ABS(CASE WHEN [Type] = 'Actual' THEN JAN ELSE 0 END)) TotalJunActual
, SUM(ABS(CASE WHEN [Type] = 'Forecast' THEN JAN ELSE 0 END)) TotalJunForecast
, SUM(ABS(CASE WHEN [Type] = 'Actual' THEN JAN + Feb + Mar ELSE 0 END)) TotalActual
, SUM(ABS(CASE WHEN [Type] = 'Forecast' THEN JAN + Feb + Mar ELSE 0 END)) TotalForecast
FROM (
SELECT
[Type]
, SUBSTRING(ID, CHARINDEX('_',ID,1) + 1,LEN(ID) - CHARINDEX('_',ID,1) + 1) ID
, DateUpload
, SUM(Jan) Jan
, SUM(Feb) Feb
, SUM(Mar) Mar
FROM test
GROUP BY
[Type]
, SUBSTRING(ID, CHARINDEX('_',ID,1) + 1,LEN(ID) - CHARINDEX('_',ID,1) + 1)
, DateUpload
) D
GROUP BY
ID
, DateUpload
) C
结果:
| ID | DateUpload | error_jan |
|--------|------------|-----------|
| Apples | 2018-01-01 | 0.076923 |
| Apples | 2018-02-01 | 0.086956 |