0

我们有 2 个表:用户和状态

状态表有一个user_id、status 和occured_on。状态为“已删除”或“已添加”,并且occured_on 是删除或添加用户的日期。

我需要当前添加的用户。即,最新状态记录被“添加”的所有(不同的)用户。

我正在使用 Rails,并尝试过:

User
  .joins(:statuses)
  .where('statuses.status = ?', 'added')
  .order('statuses.occured_on DESC')
  .uniq

转换为 SQL:

SELECT DISTINCT users.* 
FROM users
INNER JOIN statuses
ON statuses.user_id = users.id 
WHERE statuses.status = 'added' 
ORDER BY statuses.occured_on DESC

这给了我错误:

PG::Error: ERROR:  for SELECT DISTINCT, ORDER BY expressions must appear in select list
   LINE 1: ...statuses.status = 'added') ORDER BY statuses.oc...

我很高兴知道可以工作的 Rails 代码或直接的 SQL。

另外,如果可能的话,我不喜欢子选择。

4

2 回答 2

1

考虑以下数据库架构更改:

状态表:

StatusId
Status
UserId
ActiveFrom
ActiveTo

之后,您可以添加其他检查,例如:

CONSTRAINT chk_from_to CHECK (ActiveFrom <= ActiveTo)

然后您的查询将类似于:

   SELECT users.*
   FROM users 
   JOIN statuses ON UserId = users.user_id AND ActiveFrom < CURRENT_TIMESTAMP AND ActiveTo > CURRENT_TIMESTAMP
   WHERE statuses.Status = 'active'

使用这种结构,您可能需要更改更改状态的方式,但根据我自己的经验,这种结构更加灵活,并且更易于查询。

于 2012-10-05T14:33:39.720 回答
0
SELECT * FROM users INNER JOIN statuses ON users.id=statuses.user_id WHERE statuses.status='added' ORDER BY statuses.occured_on

澄清后,我认为该架构不适合您的目标。您能否阐明为什么您希望该表中包含状态更改历史记录?我对此的一般做法是,应该将活动用户包含在一个名为 projects_users 的表中,其中包含 project_id、user_id。当它们被“删除”时,它们应该从该表中删除。操作日志(在项目中添加和删除用户)应存储在单独的表中。

鉴于您当前的设计,我不知道编写此查询的好方法。即使您修复了错误,这也会在 MySQL 中运行无错误(这正是您所拥有的)

SELECT DISTINCT `users`.* FROM `users`
INNER JOIN `projects_users`
ON `users`.`id`=`projects_users`.`user_id`
WHERE `status`='added'
ORDER BY `projects_users`.`occured_on` DESC

它仍然无法为您提供正确的结果。ORDER BY 子句只会让您获得对“添加”的最新更改,它不能保证没有更新的“删除”操作。为此,您需要将每个最近添加的记录的日期与最近删除的记录的日期进行比较,对于每个用户来说,这是一场噩梦。

于 2012-10-05T14:00:19.917 回答