我需要从表中计算积压:
组件(ProductId,ComponentId,Status,StatusDate)
其中ComponentId,Status和StatusDate是主键。 ProductId是外键。例如:
prod1, comp1, 01, 05/01/2009
prod1, comp1, 02, 05/01/2009
prod1, comp1, 03, 06/01/2009
prod1, comp1, 01, 07/01/2009
prod1, comp1, 02, 20/01/2009
prod2, comp2, 01, 22/01/2009
prod1, comp1, 02, 23/01/2009
prod1, comp1, 03, 31/01/2009
基本上我想要计算的是每周的组件数量低于03.最终用户将引入一个间隔日期,所以我需要显示间隔中的所有周,即使一周没有积压。最终用户介绍的预期结果01/01 / 2009-22 / 01/2009:
Week, Backlog
1,NULL/0
2,1
3,1
4,2
第2周的说明:comp1在一周内达到状态03,但随后又回到状态01
任何帮助都非常受欢迎,谢谢
答案 0 :(得分:1)
我猜你想做什么,但这是我最好的猜测:
首先,您的数据库中应该有一个日历表:
CREATE TABLE Calendar (
calendar_date DATETIME NOT NULL,
week_number INT NOT NULL,
CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (calendar_date)
)
GO
INSERT INTO Calendar (calendar_date, week_number) VALUES ('1/1/2009', 1)
INSERT INTO Calendar (calendar_date, week_number) VALUES ('2/1/2009', 2)
etc.
您可以根据业务需求向表中添加其他列。例如,“is_holiday”位列用于跟踪您的办公室当天是否关闭。这个表使得许多不同的查询变得微不足道。
现在为您解决问题:
SELECT
CAL.week_number,
COUNT(DISTINCT C.component_id)
FROM
Calendar CAL
LEFT OUTER JOIN Components C ON
C.status_date = CAL.calendar_date AND
C.status IN ('01', '02')
WHERE
CAL.calendar_date BETWEEN @start_date AND @end_date
GROUP BY
CAL.week_number
我使用IN作为状态因为你正在使用字符串,所以“<'03'”可能并不总能给你你想要的东西。你脑子里的'1'比'03'少吗?
此外,如果您的任何日期都有时间组件,则可能需要调整相等和BETWEEN检查。
编辑:我刚看到其他答案的评论。如果您只处理状态更改,那么以下查询应该可以工作,尽管可能有更高效的方法:
SELECT
CAL.week_number,
COUNT(DISTINCT C.component_id)
FROM
Calendar CAL
LEFT OUTER JOIN Components C ON
C.status_date <= CAL.calendar_date AND
C.status IN ('01', '02')
LEFT OUTER JOIN Components C2 ON
C2.component_id = C.component_id AND
C2.status_date > C.status_date AND
C2.status_date <= CAL.calendar_date
WHERE
CAL.calendar_date BETWEEN @start_date AND @end_date AND
C2.component_id IS NULL
GROUP BY
CAL.week_number
我不确定该产品适用于所有这些。
答案 1 :(得分:0)
这是部分答案,因为我没有看到你的例子中第3周(2009年1月11日至18日)的来源。它说明了使用计数器表来获取缺失值的行。
SELECT Counter,WeekNo, CountofStatus FROM Counter LEFT JOIN
(SELECT Format([StatusDate],"ww") AS WeekNo, COUNT(c.Status) AS CountOfStatus
FROM components c
WHERE c.StatusDate BETWEEN #1/1/2009# AND #1/22/2009#
AND c.Status<3
GROUP BY Format([StatusDate],"ww")) Comp
ON Val(Comp.Weekno)=Counter.Counter
WHERE Counter.Counter>=Val(Format(#1/1/2009#,"ww"))
AND Counter.Counter<=Val(Format( #1/22/2009#,"ww"))