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

how to select/find the table data along with the latest associated (many to many) data

我的表中具有以下关系

item.rb

1
has_one :item_shipping_detail

item_shipping_detail.rb

1
2
belongs_to  :item
has_many :shipping_statuses

status.rb

1
belongs_to  :item_shipping_detail

例如数据

项目

1
2
id   title     city      state             country
 1   Title1    Nagpur    Maharashtra       India

item_shipping_details

1
2
id   item_id    price     description
 1   1          10        Electronic

状态

1
2
3
4
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_shipping_details,状态(LATEST or MAX))

1
2
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


尝试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

子选择项中的where子句会过滤掉有较新记录的任何记录。这实际上与Mark Ba??nnister的查询(在我的Postgresql 9.1数据库上可以正常使用)相同,但是不使用分区功能。

它可能不如分区函数有效,所以如果您能弄清为什么您的表不运行(可能是8.4兼容性设置或其他原因),我将继续他的查询。


使用DISTINCT ON(PostgreSQL扩展名):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

还要考虑标准语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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


试试这个

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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


事实证明,您正在使用8.3.8(来自对已删除答案的评论),因此不能使用row_number()。这意味着我倾向于结合汇总子查询来确定哪个记录是最新的。像...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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总是意味着记录比具有较低的id的记录新,则可以将created_at的出现替换为在我的查询中。


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