2

我有一个模型submission,它has_many (和submissionstate两个表分别)。submissionssubmissionstates

submissionstates有一个外键submission_id和另一state_id列(和updated_at, id

每次如果 的状态发生变化submission,就会在submissionstates表中创建一个具有新状态的新条目。

我想显示state_id= 0并且状态是提交的最新状态的条目。

例如,asubmission有两个状态(A(state_id = 0)和 B(state_id = 1)),B 在 A 之后添加。所以我希望这个提交显示在页面上,因为即使它有 A,它不是最新状态(即 B)。

我用了:

@submissions = Submission.includes(:submissionstates).where("submissionstates.state_id = 0").all

但结果将包括所有state_id= 0 的状态,即使它们不是提交的最新状态。

为了使这项工作,我应该在查询中进行哪些更改?

4

2 回答 2

1

这并不能真正回答您的问题,但可以解决您的问题

你说

例如,一个提交有两个状态(A(state_id = 0)和B(state_id = 1)),B

这是错误的。状态意味着奇点。即水壶不能既沸腾又冷。考虑将您的州旗移动到提交表中。如果您需要知道状态何时更改,请保留您的提交状态表,但您会将其用于完全不同的目的。

通过这样做,您可以使用

@submissions = Submission.where("state" = 0)

然后,您可以根据需要为每个州设置范围,例如

scope :state_0, where(:state => 0) 这让你

@submissions = Submission.state_0

这比您的方法更具可扩展性通过保留提交状态表,您仍然可以通过使用该created_at字段列出特定提交的状态更改的日期和时间,但这比正常的实时使用更像是审计跟踪

根据评论更新

使用单独的提交状态表很好,因为它会为您提供所需的审计跟踪,但您仍应在提交表上保持当前状态。

每次状态更改时更新提交记录非常简单,可以在性能方面实现,这没什么大不了的,尤其是与尝试从 submitstates 表中确定当前状态时将面临的性能问题相比。

我是说你两者都需要。如果您在将当前状态保留在提交表上时遇到问题,请大喊大叫,我会看看我是否可以解决这个问题

于 2013-03-05T23:13:36.890 回答
1

您的数据库结构有问题!

当涉及到关系数据库时,您必须始终记住一件事:没有一般的或自动的行排序!

我的意思是:您不能依赖查询输出的顺序。问题是:DBMS 优化您的查询,如果您不调用ORDER BY它,则未定义它将返回行的顺序。(即使它看起来总是相同的顺序,它可能会在升级 DBMS 或仅仅因为一袋大米在中国掉下来而改变)。不要依赖那个!

所以只有一个合乎逻辑的解决方案:表的第三列submissionstate,自动生成的主键或时间戳。如果您不需要创建时间,请使用主键。

然后你的桌子看起来像:

id | submission_id | state_id
-----------------------------
1  | 4             | 3
2  | 8             | 3
3  | 4             | 2
4  | 6             | 1
5  | 4             | 5
6  | 8             | 0

如果我理解正确,你想要这些结果:

  • 如果你寻找submission_id = 4你想收到state_id = 5
  • 如果你寻找submission_id = 8你想收到state_id = 0
  • 如果你寻找submission_id = 6你想收到state_id = 1

正确的?


解决方案:

因此,当id给出一个字段时,您要查找的查询是:

SELECT submission_id, state_id
FROM submissionstates ss
JOIN (
  SELECT MAX(id) as id
  FROM submissionstates ss
  GROUP BY submission_id
) x
ON ss.id = x.id

如果您只想要当前 state_id = 0 的行,则:

SELECT submission_id, state_id
FROM submissionstates ss
JOIN (
  SELECT MAX(id) as id
  FROM submissionstates ss
  GROUP BY submission_id
) x
ON ss.id = x.id
WHERE state_id = 0

如果您已经有 created_at 列,请使用它而不是 id 列:

SELECT submission_id, state_id
FROM submissionstates ss
JOIN (
  SELECT MAX(created_at) as created_at
  FROM submissionstates ss
  GROUP BY submission_id
) x
ON ss.created_at = x.created_at
WHERE state_id = 0
于 2013-03-05T23:15:47.003 回答