Sql 如何在Rails中查询这个问题?
我有一个模型Sql 如何在Rails中查询这个问题?,sql,ruby-on-rails,database,Sql,Ruby On Rails,Database,我有一个模型提交,它有许多提交状态(分别有两个表提交和提交状态) submissionstates有一个外键submission\u id和另一个state\u id列(和updated\u at,id) 如果每次提交的状态发生更改,将在提交状态表中创建一个具有新状态的新条目 我想显示具有state\u id=0且状态为提交的最新状态的条目 例如,一个提交有两种状态(a(state_id=0)和B(state_id=1)),B是在a之后添加的。因此我不希望该提交显示在页面上,因为即使它有a,它也
提交
,它有许多提交状态
(分别有两个表提交
和提交状态
)
submissionstates
有一个外键submission\u id
和另一个state\u id
列(和updated\u at
,id
)
如果每次提交的状态发生更改
,将在提交状态
表中创建一个具有新状态的新条目
我想显示具有state\u id
=0且状态为提交的最新状态的条目
例如,一个提交
有两种状态(a(state_id=0)和B(state_id=1)),B是在a之后添加的。因此我不希望该提交显示在页面上,因为即使它有a,它也不是最新的状态(即B)
我用过:
@submissions = Submission.includes(:submissionstates).where("submissionstates.state_id = 0").all
但结果将包括state\u id
=0的所有状态,即使它们不是提交的最新状态
我应该在查询中更改什么才能使其正常工作?这并不能真正回答您的问题,但它解决了您的问题 你说 例如,提交有两种状态(a(state_id=0)和B) (state_id=1)),B 这是错误的。状态意味着奇点。i、 水壶不能既热又冷。 考虑将状态标志移到提交表中。 如果您需要知道状态何时更改,请保留submissionstates表,但您将使用该表用于完全不同的目的 通过这样做,您可以使用
@submissions = Submission.where("state" = 0)
然后,如果愿意,您可以为每个状态设置作用域,例如
作用域:state_0,其中(:state=>0)
这就给你留下了
@submissions = Submission.state_0
这比你的方法更具可扩展性
通过保留submissionstates表,您仍然可以使用在字段创建的来列出特定提交状态更改的日期和时间,但这比正常的实时使用更像是一个审计线索
根据评论进行更新
使用单独的submissionstates表是可以的,因为它将为您提供所需的审计跟踪,但您仍应在submissionstates表中保留当前状态
每次状态更改时更新提交记录非常简单,可以在性能方面实现,特别是与试图从submissionstates表确定当前状态时将面临的性能问题相比,这没什么大不了的
我是说你两者都需要。如果您在提交表中保留当前状态时遇到问题,请大声喊叫,我会看看是否可以解决此问题。您的数据库结构有问题
当涉及到关系数据库时,您必须始终记住一件事:并没有行的常规或自动排序强>
我的意思是:您不能依赖于查询输出的顺序。问题是:DBMS优化了您的查询,如果您不调用orderby
,则不会定义返回行的顺序。(即使看起来总是一样的顺序,但在升级数据库管理系统时可能会发生变化,或者仅仅因为中国有一袋大米倒下了)不要依赖它强>
因此,只有一个逻辑解决方案:为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\u id=4
您希望接收state\u id=5
- 如果您查找
submission\u id=8
您希望接收state\u id=0
- 如果您查找
submission\u id=6
您希望接收state\u 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
如果只需要当前状态为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
如果您已经在列中创建了一个_,请使用它而不是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
这并不能解决问题。是的,需要考虑排序顺序,但通过create_at或updated_at列进行排序没有错,但它没有解释如何获得John正在寻找的结果,也没有解决缩放能力的问题。随着时间的推移,这种方法将逐渐停止。op正在寻找当前状态为0的所有状态。当然,通过在
创建的进行排序没有问题,但是他没有写任何关于此字段的内容,所以我想说,没有这样的专栏。我已经编写了一个查询,当给出一个自动递增的id
时,它解决了他的问题。好的,如果这是真的,我将扩展我的解决方案;)当然,在列中创建了一个_。究竟为什么没有呢?要想去掉那个专栏需要一些努力,这样约翰就会知道,如果他真的这么做了,那么它就不存在了。谢谢你的回答。我决定使用一个单独的submissionstates
表,只是因为我不想在每次状态更改时更新条目,而是想插入一个新条目来跟踪每个状态更改,这更像是一种模型版本控制方法。是的,你是对的,一次提交不能同时有多个状态,这就是为什么我总是想要最新的状态:)