如何选择/查找表数据以及最新的关联(多对多)数据

时间:2012-01-11 08:34:52

标签: sql ruby-on-rails postgresql rails-postgresql

我的表格中有以下关系

item.rb的

has_one :item_shipping_detail

item_shipping_detail.rb

belongs_to  :item
has_many :shipping_statuses

status.rb

belongs_to  :item_shipping_detail

实施例。数据

id   title     city      state             country
 1   Title1    Nagpur    Maharashtra       India

item_shipping_details

id   item_id    price     description
 1   1          10        Electronic

以下状态

id   item_shipping_detail_id    status_city     status_state   status_country  created_at 
 1   1                           Mumbai         Maharashtra    India           2012-01-09 07:58:16
 2   1                           Akola          Maharashtra    India           2012-01-10 07:58:16
 3   1                           Nagpur         Maharashtra    India           2012-01-11 07:58:16

我希望使用单个查询获得以下结果(item,item_shipping_details,状态(LATEST or MAX)

id title city     state         country  price  description  status_city  status_state    status_country
 1 Title1 Nagpur  Maharashtra    India    10    Electronic   Nagpur       Maharashtra    India

JYI: - 我正在使用Rails 2.3.8

5 个答案:

答案 0 :(得分:4)

尝试:

select i.id,
       i.title,
       i.city,
       i.state,
       i.country,
       d.price,
       d.description,
       s.status_city,
       s.status_state,
       s.status_country
from items i
left join item_shipping_details d on i.id = d.item_id
left join 
   (select s1.* from statuses s1
     where not exists 
           (select * from statuses s2
        where 
                s2.item_shipping_detail_id = s1.item_shipping_detail_id 
                and s2.created_at> s1.created_at) )  s
on d.id = s.item_shipping_detail_id

subselect上的where子句筛选出有新记录的记录。这实际上与Mark Ba​​nnister的查询(在我的Postgresql 9.1数据库上工作正常)相同,但不使用分区函数。

它可能没有分区功能那么高效,所以如果你可以解决为什么你的运行没有运行(可能是8.4兼容性设置或什么?)我会继续他的查询。

答案 1 :(得分:2)

使用DISTINCT ON,postgresql扩展名:

select distinct on(i.id, d.id)
   i.id,
   i.title,
   i.city,
   i.state,
   i.country,
   d.price,
   d.description,
   s.status_city,
   s.status_state,
   s.status_country
from items i
left join item_shipping_details d on i.id = d.item_id
left join statuses s on s.item_shipping_detail_id = d.id
order by i.id, d.id, s.created_at desc

还要考虑标准语法:

select * from (
select i.id,
   i.title,
   i.city,
   i.state,
   i.country,
   d.price,
   d.description,
   s.status_city,
   s.status_state,
   s.status_country,
   row_number() over(partition by d.id, i.id order by s.created_at desc) as rn
from items i
left join item_shipping_details d on i.id = d.item_id
left join statuses s on s.item_shipping_detail_id = d.id
) tab where tab.rn = 1

答案 2 :(得分:0)

您必须在状态中加入“内容”,以便选择最新状态,例如到达日期等。在提供额外的列之前,无法回答您的问题。

答案 3 :(得分:0)

事实证明您使用8.3.8(来自对已删除答案的评论),您无法使用row_number()。这意味着我倾向于加入聚合子查询以确定哪条记录是最新的。有点像...

SELECT
   i.id,
   i.title,
   i.city,
   i.state,
   i.country,
   d.price,
   d.description,
   s.status_city,
   s.status_state,
   s.status_country
FROM
  items                    i
LEFT JOIN
  item_shipping_details    d
    ON i.id = d.item_id
LEFT JOIN
  (SELECT item_shipping_detail_id, MAX(created_at) AS created_at FROM statuses GROUP BY item_shipping_detail_id)   lookup
    ON lookup.item_shipping_detail_id = d.id
LEFT JOIN
  statuses                 s
    ON  s.item_shipping_detail_id = lookup.item_shipping_detail_id
    AND s.created_at              = lookup.created_at

注意: 要优化子查询和连接,需要对statuses表进行适当的索引; (item_shipping_detail_id, created_at)

如果您在(item_shipping_detail_id, id)上有索引,并且可以保证较高的id 始终表示记录比具有较低{{1}的记录更新},可以在我的查询中用id替换created_at的出现。

答案 4 :(得分:0)

试试这个

select distinct on(i.id, d.id)
   i.id,
   i.title,
   i.city,
   i.state,
   i.country,
   d.price,
   d.description,
   s.status_city,
   s.status_state,
   s.status_country
from items i
left join item_shipping_details d on i.id = d.item_id
left join statuses s on s.item_shipping_detail_id = d.id
where s.id = (select Max(id) as id from statuses where item_shipping_detail_id = d.id)
order by i.id, d.id desc