Remains
- 所有产品交易
Stock
- 产品库存
DimDate
- 时间表
计算库存:
20050115
产品 - 1
仓库 - 6
20050201
和Stock
表格与weight
,stock
,cost
划分为同一产品和仓库。 Remains
中从所选日期到月末的所有交易相加,并从Stock
表下个月的第一天我正在使用它:
CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,CAST(convert(varchar,t.DateKey) as datetime)))-1),DATEADD(mm,1,CAST(convert(varchar,t.DateKey) as datetime))),112)
示例Remains
:
| TIMEKEY | PRODUCT | WAREHOUSE | COST | STOCK | WEIGHT |
|----------|---------|-----------|------|-------|--------|
| 20050114 | 1 | 6 | 100 | 5 | 15 |
| 20050118 | 1 | 6 | 200 | 10 | 30 |
| 20050125 | 1 | 6 | -100 | -5 | -15 |
Stock
:
| TIMEKEY | PRODUCT | WAREHOUSE | COST | STOCK | WEIGHT |
|----------|---------|-----------|------|-------|--------|
| 20050201 | 1 | 6 | 515 | 55 | 53 |
| 20050301 | 2 | 8 | 20 | 3 | 2 |
| 20050301 | 3 | 9 | 16 | 2 | 3 |
| 20050301 | 4 | 10 | 49 | 8 | 5 |
| 20050401 | 5 | 26 | 59 | 9 | 10 |
结果(我的查询)按产品1,仓库6和第一个月按天计算库存:
| DATEKEY | PRODUCT | WAREHOUSE | WEIGHT | STOCK | COST |
|----------|---------|-----------|--------|--------|--------|
| 20050101 | 1 | 6 | 23 | 45 | 315 |
| 20050102 | 1 | 6 | 23 | 45 | 315 |
| 20050103 | 1 | 6 | 23 | 45 | 315 |
| 20050104 | 1 | 6 | 23 | 45 | 315 |
| 20050105 | 1 | 6 | 23 | 45 | 315 |
| 20050106 | 1 | 6 | 23 | 45 | 315 |
| 20050107 | 1 | 6 | 23 | 45 | 315 |
| 20050108 | 1 | 6 | 23 | 45 | 315 |
| 20050109 | 1 | 6 | 23 | 45 | 315 |
| 20050110 | 1 | 6 | 23 | 45 | 315 |
| 20050111 | 1 | 6 | 23 | 45 | 315 |
| 20050112 | 1 | 6 | 23 | 45 | 315 |
| 20050113 | 1 | 6 | 23 | 45 | 315 |
| 20050114 | 1 | 6 | 38 | 50 | 415 |
| 20050115 | 1 | 6 | 38 | 50 | 415 |
| 20050116 | 1 | 6 | 38 | 50 | 415 |
| 20050117 | 1 | 6 | 38 | 50 | 415 |
| 20050118 | 1 | 6 | 68 | 60 | 615 |
| 20050119 | 1 | 6 | 68 | 60 | 615 |
| 20050120 | 1 | 6 | 68 | 60 | 615 |
| 20050121 | 1 | 6 | 68 | 60 | 615 |
| 20050122 | 1 | 6 | 68 | 60 | 615 |
| 20050123 | 1 | 6 | 68 | 60 | 615 |
| 20050124 | 1 | 6 | 68 | 60 | 615 |
问题/疑问 产品库存没有结束所以我需要显示整月的结果(或我在where子句中选择的范围),而不仅仅是24天。如果这是不可能的,也许有人可以帮助我用于计算股票的当前查询优化。我正在使用ms sql 2008r2
SELECT t.DateKey, r.Product, r.Warehouse,
(SELECT [Weight]
FROM Stock
WHERE Timekey = CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,CAST(convert(varchar,t.DateKey) as datetime)))-1),DATEADD(mm,1,CAST(convert(varchar,t.DateKey) as datetime))),112)
AND Product = r.Product
AND Warehouse = r.Warehouse)-SUM(r.Weight) AS [Weight],
(SELECT Stock
FROM Stock
WHERE Timekey = CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,CAST(convert(varchar,t.DateKey) as datetime)))-1),DATEADD(mm,1,CAST(convert(varchar,t.DateKey) as datetime))),112)
AND Product = r.Product
AND Warehouse = r.Warehouse)-SUM(Stock) as Stock,
(SELECT Cost
FROM Stock
WHERE Timekey = CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,CAST(convert(varchar,t.DateKey) as datetime)))-1),DATEADD(mm,1,CAST(convert(varchar,t.DateKey) as datetime))),112)
AND Product = r.Product
AND Warehouse = r.Warehouse)-SUM(Cost) AS Cost
FROM DimDate t, Remains r
WHERE t.DateKey < r.Timekey
AND r.Timekey <= CONVERT(VARCHAR(25),DATEADD(dd,-(DAY(DATEADD(mm,1,CAST(convert(varchar,t.DateKey) as datetime)))-1),DATEADD(mm,1,CAST(convert(varchar,t.DateKey) as datetime))),112)
AND t.DateKey >= 20050101
and r.Product = '1'
and r.Warehouse = 6
GROUP BY t.DateKey, r.Product, r.Warehouse
答案 0 :(得分:0)
很难判断它是否在较小的数据集上更快,但以下内容看起来有更好的查询计划。方法是只加入库存表一次而不是三次。
with x as (
select
t.DateKey,
r.Product,
r.Warehouse,
sum(r.Weight) as Weight,
sum(Stock) as Stock,
sum(Cost) as Cost,
(t.DateKey / 100
+ Case t.DateKey / 100 % 100 when 12 Then 89 else 1 end)
* 100 + 1 as TimeKey
from
DimDate t,
Remains r
where
t.DateKey < r.Timekey and
r.Timekey <= (
t.DateKey / 100
+ Case t.DateKey / 100 % 100 when 12 Then 89 else 1 end)
* 100 + 1 and
t.DateKey >= 20050101 and
r.Product = 1 and
r.Warehouse = 6
group by
t.DateKey,
r.Product,
r.Warehouse
) select
x.DateKey,
x.Product,
x.Warehouse,
s.Weight - x.Weight as Weight,
s.Stock - x.Stock as Stock,
s.Cost - x.Cost as Cost
From
x
left outer join
Stock s
on s.TimeKey = x.TimeKey and
s.Product = x.Product and
s.Warehouse = x.Warehouse;
<强> Example SQLFiddle 强>
如果您有机会重新设计此架构,请记住date数据类型仅使用三个字节,而int则为四个字节。
它可能对整体查询成本没有太大贡献,但您可以将“下个月的开始”值存储为DimDate表上的计算列。它使查询更容易阅读。
create table DimDate (
[DateKey] int,
StartOfNextMonthKey as (
DateKey / 100
+ Case DateKey / 100 % 100 when 12 Then 89 else 1 end
) * 100 + 1 persisted
);
然后查询
with x as (
select
t.DateKey,
r.Product,
r.Warehouse,
sum(r.Weight) AS [Weight],
sum(Stock) as Stock,
sum(Cost) AS Cost,
t.StartOfNextMonthKey
from
DimDate t,
Remains r
where
t.DateKey < r.Timekey AND
r.Timekey <= t.StartOfNextMonthKey and
t.DateKey >= 20050101 and
r.Product = 1 and
r.Warehouse = 6
group by
t.DateKey,
r.Product,
r.Warehouse,
t.StartOfNextMonthKey
) select
x.DateKey,
x.Product,
x.Warehouse,
s.Weight - x.Weight as Weight,
s.Stock - x.Stock as Stock,
s.Cost - x.Cost as Cost
From
x
left outer join
Stock s
on s.TimeKey = x.StartOfNextMonthKey and
s.Product = x.Product and
s.Warehouse = x.Warehouse;
<强> Example SQLFiddle 强>