我正在开发一个不断更新的生产表,它还处于起步阶段,但最终每分钟可能有多次插入(并且可能会达到数百万条目)。我对表结构无控制或输入数据的方式。
我需要计算_COFF在机器具有_SETUP状态后的数量。此计数必须每隔15分钟至少进行。该ID用作另一个表中的键,并且必须与输出中的MachineNumber和PartNumber相关联。 (下面的样本输出)
以下是我的工作内容:
'生产'表:
+---------------+---------------------+---------+------------+--------+
| MachineNumber | DateTime | Comment | PartNumber | Status |
+---------------+---------------------+---------+------------+--------+
| 1 | 11/11/2014 12:12:32 | | 104 | _SETUP |
| 1 | 11/11/2014 12:12:40 | 155 | 104 | _ID |
| 1 | 11/11/2014 12:12:45 | | 104 | _CON |
| 1 | 11/11/2014 12:16:45 | | 104 | _COFF |
| 1 | 11/11/2014 12:16:46 | | 104 | _CON |
| 1 | 11/11/2014 12:20:46 | | 104 | _COFF |
| 2 | 11/11/2014 12:20:50 | | 223 | _SETUP |
| 1 | 11/11/2014 12:21:00 | | 104 | _CON |
| 1 | 11/11/2014 12:23:00 | | 104 | _COFF |
| 2 | 11/11/2014 12:25:00 | 543 | 223 | _ID |
| 2 | 11/11/2014 12:25:20 | | 223 | _CON |
| 2 | 11/11/2014 12:26:20 | | 223 | _COFF |
... ... ... ... ...
+---------------+---------------------+---------+------------+--------+
目前我使用游标获取以下输出:
+---------------+------------+-----+-------------+
| MachineNumber | DateTime | ID | _COFF Count |
+---------------+------------+-----+-------------+
| 1 | 11/11/2014 | 155 | 3 |
| 2 | 11/11/2014 | 543 | 1 |
+---------------+------------+-----+-------------+
无论如何要做到这一点比循环(可能)一百万个条目更好?如何删除已经循环的表中的记录,并将输出存储在另一个表中?
编辑:每台机器每个部件只有一个_SETUP和一个_ID,但每台机器会有多个部件(因此表中的每台机器都有多个_SETUP和_ID)。
答案 0 :(得分:0)
select table.machinenumber, timestamp.starttime, id.comment, count(*)
from table
join ( select MachineNumber, min(comment) as commment
from table
where Status = '_ID'
and comment is not null
group by MachineNumber ) as id
on id.MachineNumber = table.machinenumber
join ( select MachineNumber, min(datetime) as starttime
from table
where Status = '_SETUP'
group by MachineNumber ) as timestamp
on timestamp.ID = table.ID
and timestamp.starttime < table.datetime
and table.Status = '_CON'
group by table.machinenumber, timestamp.starttime, id.comment
答案 1 :(得分:0)
最好的办法是创建一个触发器,重置机器的上次设置日期,然后在索引视图中使用它。
假设您的表名为Status
:
CREATE INDEX
IX_Status_Machine_Status_DateTime
ON Status (machineNumber, status, dateTime)
GO
CREATE UNIQUE INDEX
UX_Status_Machine_Part__Id
ON Status (machineNumber, partNumber)
WHERE status = '_ID'
CREATE TABLE
Status_LastSetup
(
machineNumber INT NOT NULL PRIMARY KEY,
partNumber INT NOT NULL,
lastSetup DATETIME NOT NULL
)
GO
CREATE TRIGGER
TR_Status_All
ON Status
AFTER INSERT, UPDATE, DELETE
AS
WITH c AS
(
SELECT machineNumber
FROM INSERTED
UNION ALL
SELECT machineNumber
FROM DELETED
),
t AS
(
SELECT sls.*
FROM c
JOIN Status_LastSetup sls
ON sls.machineNumber = c.machineNumber
),
s AS
(
SELECT *
FROM c
CROSS APPLY
(
SELECT TOP 1
partNumber, dateTime
FROM Status st
WHERE st.machineNumber = c.machineNumber
AND st.status = '_STATE'
ORDER BY
dateTime DESC
)
)
ON t.machineNumber = s.machineNumber
WHEN NOT MATCHED BY TARGET THEN
INSERT (machineNumber, partNumber, lastSetup)
VALUES (s.machineNumber, s.partNumber, s.dateTime)
WHEN MATCHED THEN
UPDATE
SET t.dateTime = s.dateTime,
t.partNumber = s.partNumber
WHERE EXISTS
(
SELECT t.dateTime, t.partNumber
EXCEPT
SELECT s.dateTime, s.partNumber
)
WHEN NOT MATCHED BY SOURCE THEN
DELETE
GO
CREATE VIEW
V_Status_CoffCount
WITH SCHEMABINDING
AS
SELECT s.machineNumber,
COUNT_BIG(*) cnt
FROM dbo.Status_LastSetup sls
JOIN dbo.Status s
ON s.machineNumber = sls.machineNumber
AND s.status = '_COFF'
AND s.dateTime >= sls.lastSetup
GROUP BY
s.machineNumber
GO
CREATE UNIQUE CLUSTERED INDEX
UX_V_Status_CoffCount_Machine
ON V_Status_CoffCount (machineNumber)
GO
一旦启动并运行,只需运行此查询:
SELECT s.machineNumber, sls.lastSetup, comment id, cnt
FROM V_Status_CoffCount scc WITH (NOEXPAND)
JOIN Status_LastSetup sls
ON sls.machineNumber = scc.machineNumber
LEFT JOIN
Status s
ON s.machineNumber = sls.machineNumber
AND s.partNumber = sls.partNumber
AND s.status = '_ID'
它的执行时间与您拥有的机器数量呈线性关系,并且(几乎)不依赖于Status
中的条目数。
在SQLFiddle上看到这一切:http://sqlfiddle.com/#!6/9671c/2