1

我有一个在 PostgreSQL 上运行的 rails 3.2 应用程序,并且有一些我想在视图中显示的数据,这些数据以这种结构存储在数据库中:

+----+--------+------------------+--------------------+
| id | name   | sched_start_date | task               |
+----+--------+------------------+--------------------+
| 1  | "Ben"  | 2013-03-01       | "Check for debris" |
+----+--------+------------------+--------------------+
| 2  | "Toby" | 2013-03-02       | "Carry out Y1.1"   |
+----+--------+------------------+--------------------+
| 3  | "Toby" | 2013-03-03       | "Check oil seals"  |
+----+--------+------------------+--------------------+

我想显示每个名称的任务列表,以及按名称排序的名称ASCsched_start_date它们应该看起来像......


2013-03-01 – 检查碎片

托比
2013-03-02 – 开展Y1.1
2013-03-03 – 检查油封

我开始采用的方法是对唯一名称运行查询并将它们排序sched_start_date ASC,然后对每个名称运行查询以获取它们的任务。

要获取唯一名称列表,SQL 应如下所示。

select * 
from (
   select distinct on (name) name, sched_start_date 
   from tasks
) p 
order by sched_start_date;

我想知道这是否是正确的方法(查询唯一名称,然后为他们的所有任务运行另一个查询),或者是否有更好的 rails 方式。

4

2 回答 2

1

要像您描述的那样对数据进行排序,您可能希望在子句中使用min()as window function :ORDER BY

SELECT name, sched_start_date, task
FROM   tasks
ORDER  BY min(sched_start_date) OVER (PARTITION BY name), 1, 2, 3

您的原始查询需要一个额外的ORDER BY项目来获取每个名称的最早日期:

SELECT DISTINCT ON (name) name, sched_start_date, task
FROM   tasks
ORDER  BY 1, 2, 3;

我还添加了task( 3) 作为打破关系的最后ORDER BY一项,以防每个日期有多个。

但输出仍按 排序name,而不是按排序date

将所有数据填充到一列中的特殊格式有点复杂:

SELECT one_col
FROM  (
    WITH x AS (
        SELECT name, min(sched_start_date) AS min_start
        FROM   tasks
        GROUP  BY 1
        )
    SELECT 2 AS rnk, name
          ,sched_start_date::text || ' – ' || task AS one_col
          ,sched_start_date, min_start
    FROM   tasks
    JOIN   x USING (name)

    UNION ALL
    SELECT 1 AS rnk, name, name, NULL::date, min_start
    FROM   x

    ORDER  BY min_start, name, rnk, sched_start_date, task
    ) y
于 2013-04-01T15:20:02.287 回答
0

假设您的模型中有关联,您将能够运行

@employees = Employee.order(:name, :sched_start_date, :task).includes(:tasks)

然后你可以遍历它们:

@employees.each do |employee|
  employee.name
  employee.tasks.each do |task|
    task.name
  end
end

这不会完全符合您的需求,但应该告诉您从哪里开始。

于 2013-04-01T13:54:45.273 回答