2

我有两张表,chartschart_entries想获得当前的前 5 个图表位置(基于选择chart_entries给定位置的最新位置)。

有没有办法让它成为一个单一的查询?理想情况下,我的图表最多可以有 500 个位置,因此像这样进行多个查询并不可行。

在rails中,我目前正在使用这种方法Chart.rb

def table
  (1..5).each do |i|
    chart_entries.where(position: i).order('entered_at DESC').first
  end
end

生成以下 SQL

SELECT "chart_entries".* FROM "chart_entries" WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" = 1 ORDER BY entered_at DESC LIMIT 1
SELECT "chart_entries".* FROM "chart_entries" WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" = 2 ORDER BY entered_at DESC LIMIT 1
SELECT "chart_entries".* FROM "chart_entries" WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" = 3 ORDER BY entered_at DESC LIMIT 1
SELECT "chart_entries".* FROM "chart_entries" WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" = 4 ORDER BY entered_at DESC LIMIT 1
SELECT "chart_entries".* FROM "chart_entries" WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" = 5 ORDER BY entered_at DESC LIMIT 1

这是表结构(postgresql)

CREATE TABLE chart_entries (
  id integer NOT NULL,
  chart_id integer,
  entity_id integer,
  "position" integer,
  entered_at timestamp without time zone,
  locale character varying(255)
);

CREATE TABLE charts (
  id integer NOT NULL,
  name character varying(255)
);

这是我的最终解决方案

chart_entries.where(position: [1..5]).group('position, id').having('entered_at = MAX(entered_at)').order('position ASC')
4

2 回答 2

2

这将是一个很好的候选人GROUP BY

SELECT
    *
FROM
    chart_entries
WHERE
    chart_id = 1
    AND position BETWEEN 1 AND 5
GROUP BY
    position
HAVING
    entered_at = MAX(entered_at)

使用GROUP BY将为每个位置选择一行。该HAVING子句应按日期选择最新的一个(您也可以为此使用主键,因为它应该是最新的 - 除非您插入自定义日期)。

无需编写每个position可用的个体,您可以BETWEENWHERE子句中使用来获取“ 1 到 5之间的所有位置”(或任何您的范围)。

于 2012-10-17T12:52:29.660 回答
1

使用MAX&GROUP BY

SELECT MAX("chart_entries".id) FROM "chart_entries" 
WHERE "chart_entries"."chart_id" = 1 AND "chart_entries"."position" IN (1,2,3,4,5) 
ORDER BY entered_at DESC 
GROUP BY  "chart_entries"."position" 
于 2012-10-17T12:52:21.127 回答