如何实现数据库动作表

时间:2017-08-30 17:28:27

标签: sql sql-server-2012

我想设计一个动作表,它模拟简单的消息动作队列。表中的每一行都是要完成的操作,它具有创建日期,处理日期和发送日期,因此具有执行状态。可能会重新启动该操作。

此外,某些消息未发送,但通过映射表附加到其他实体。所以是不同类型的消息,可以通过message_type整数字段来表示。

Action表结构现在如下(设计草案):

CREATE TABLE Action
(
id INT NOT NULL PRIMARY KEY,
msg_id INT NOT NULL,
msg_type INT NOT NULL,
msg NVARCHAR(1000) NOT NULL,
creation_date DATETIME2 NOT NULL,
processing_date DATETIME2 NULL,
sending_date DATETIME2 NULL
status INT NOT NULL
)

问题是现在每行包含" instance"对于消息发送操作,如果重新启动操作,则必须创建新行。这使得对表的sql查询变得很复杂,因为必须限制重新启动发送未发送的消息的操作。这可能需要对表本身进行多次自连接。必须保存先前的尝试,因此这就是为什么不重用上一行(a.k.a实例)的消息操作的原因。

我可以尝试通过以下方式检索上一次(重新)动作的开始尝试:

SELECT a.*, b.* FROM Action a INNER JOIN Action b ON a.msg_id = b.msg_id

因此,如果存在由此内部联接产生的行,则表中必须存在至少重启一次的消息操作。但这还不足以解决问题,因为可能会有多次重启尝试,因此会有几个INNER JOIN / self-join。

如何重新设计表,以便可以有效地用于存储消息操作以及之前重新启动的尝试?或者我应该以某种方式重新设计查询?

示例数据以澄清问题:

行:

id = 1, msg_id = 1, msg_type = 1, msg = "Administrator mail: Everything is fine", creation_date = 31/12/2016, status = 10

id = 2, msg_id = 2, msg_type = 1, msg = "Administrator mail: Please ensure that service is running", creation_date = 1/1/2017, status = 6

id = 3, msg_id = 2, msg_type = 1, msg = "Administrator mail: Please ensure that service is running", creation_date = 1/1/2017, status = 6

id = 4, msg_id = 2, msg_type = 1, msg = "Administrator mail: Please ensure that service is running", creation_date = 1/1/2017, status = 1

状态代码的含义:

status 6 = action failed
status 1 = action enqueued
status 3 = action started
status 10 = action completed succesfully

1 个答案:

答案 0 :(得分:0)

如果您需要的只是每个消息ID的计数,您只需使用以下内容即可。我添加了一个“where”子句来排除具有完整状态和“having”子句的消息,以说明如何根据给定msg_id的计数来限制集合。

select
    msg_id,
    count(msg_id) as msg_count
from Action
where msg_id not in
(
    select 
        msg_id
    from Action
    where Status = 10
)
group by msg_id
having count(msg_id) > 5

如果您需要插入行,请创建“id”列和IDENTITY字段并尝试以下内容:

Insert Into Action
(
    msg_id,
    msg_type,
    msg,
    creation_date,
    status
)
select
    msg_id,
    1,               -- you didn't explain this field, but all the values are "1", so...
    'Administrator mail: Please ensure that service is running',
    get_date(),
    1                -- from your list of statuses
from Action
where msg_id not in
(
    select 
        msg_id
    from Action
    where Status = 10
)
group by msg_id
having count(msg_id) < 5       -- use whatever count criteria you want here, of course