【问题标题】:Is there a way to sort a parent record by the earliest date associated with its child records?有没有办法按与其子记录关联的最早日期对父记录进行排序?
【发布时间】:2019-04-12 16:38:21
【问题描述】:

我有两张表,一张发票表和一张工作日表。发票有很多工作日。

工作日架构具有:

invoice_id:整数,日期:日期

假设发票模式现在在表中只有一个 id。

在我的应用程序视图中,我想打印出所有预装了所有工作日的发票。对于每张发票,子工作日应按日期排序。即使发票上没有日期字段,我想知道是否可以按所有相应儿童工作日中的最早日期对发票进行排序?

目标是能够生成类似于以下内容的视图:

Invoice date range: Jan 02, 2019 - Jan 03, 2019
Workdays: 
Jan 02, 2019
Jan 03, 2019

Invoice date range: Jan 05, 2019 - Jan 06, 2019
Workdays:
Jan 05, 2019
Jan 06, 2019

我正在使用这样的查询:select * from invoice inner join workdays on workdays.invoice_id = invoice.id order by workdays.date

但由于未指定发票上的顺序,因此可能会出现发票乱序。我不知道有任何其他方法可以指定发票上的排序顺序,而不会将最早的工作日。日期缓存到新列的父(发票)中,然后按该额外列排序。

更新:我使用 postgres 和 mysql。我所说的“视图”不是指数据库(物化)视图,而是指模型、视图、控制器、视图层。

【问题讨论】:

  • 您必须使用exists 子查询,如果您重用表,则必须使用With 来搜索max() 日期和left 之类的内容,例如“即使没有日期字段发票”。没有数据、例子等很难回答。
  • 您使用的是哪个DBMS 产品? “SQL”只是一种查询语言,而不是特定数据库产品的名称。请为您正在使用的数据库产品添加tag postgresql, oracle, sql-server, db2, ...
  • 你想要的输出是不可能的,因为每一行包含不同数量的列。在关系数据库中,表、视图或 SELECT 语句的结果在每一行中始终具有相同数量的列。并且该列的数据类型对于所有行都是固定的。

标签: mysql sql postgresql


【解决方案1】:

类似:

select 
    i.id, i.comment,
    min(wd.date) as invoice_range_from, max(wd.date) as invoice_range_to
from invoice i
left join workdays wd on i.id = wd.invoice_id
group by i.id
order by min(wd.date), max(wd.date)

如果您想在一次服务器往返中检索您的父子节点,请使用您的 RDBMS 的 JSON 或 XML 功能,特别是如果您的客户端应用程序无论如何都会使用 JSON,您可以使用以下方法。例如,

现场测试:https://dbfiddle.uk/?rdbms=postgres_11&fiddle=0b1ce002c4380a3542387209c3c43fae

select 
    i.id, i.comment,
    min(wd.date) as invoice_from, max(wd.date) as invoice_to,
    json_agg(json_build_object('date', wd.date)) as workdays_data
from invoice i
left join workdays wd on i.id = wd.invoice_id
group by i.id
order by min(wd.date), max(wd.date)

输出:

id  comment invoice_from    invoice_to  workdays_data
1   Hello   2019-01-02      2019-01-03  [{"date" : "2019-01-02"}, {"date" : "2019-01-03"}]
2   Hola    2019-01-05      2019-01-06  [{"date" : "2019-01-05"}, {"date" : "2019-01-06"}]

否则,您将不得不使用 ORM 的批处理功能。如果没有功能强大的 ORM,则需要手动使查询最小化服务器往返。

如果想全力以赴地使用 RDBMS 的 JSON 功能一次性渲染树状数据,您可以:)

现场测试:https://dbfiddle.uk/?rdbms=postgres_11&fiddle=1ed3105719ed033ba568e01b3d97c234

with a as 
(
    select 
        i.id, i.comment,
        min(wd.date) as invoice_range_from, max(wd.date) as invoice_range_to,
        json_agg(json_build_object('date', wd.date)) as workdays_data
    from invoice i
    left join workdays wd on i.id = wd.invoice_id
    group by i.id
    order by min(wd.date), max(wd.date)
)
select json_agg(a.*) from a;

输出:

[
    {
        "id": 1,
        "comment": "Hello",
        "invoice_range_from": "2019-01-02",
        "invoice_range_to": "2019-01-03",
        "workdays_data": [
            {
                "date": "2019-01-02"
            },
            {
                "date": "2019-01-03"
            }
        ]
    },
    {
        "id": 2,
        "comment": "Hola",
        "invoice_range_from": "2019-01-05",
        "invoice_range_to": "2019-01-06",
        "workdays_data": [
            {
                "date": "2019-01-05"
            },
            {
                "date": "2019-01-06"
            }
        ]
    }
]

架构:

create table invoice
(
  id int primary key,
  comment text not null
);


create table workdays
(
  invoice_id int not null references invoice(id),
  id int not null generated by default as identity primary key,
  date date not null
);


insert into invoice(id, comment) values
(1, 'Hello'),
(2, 'Hola');

insert into workdays(invoice_id, date) values
(1, '2019-1-2'),
(1, '2019-1-3'),
(2, '2019-1-5'),
(2, '2019-1-6');

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-24
    • 1970-01-01
    相关资源
    最近更新 更多