Есть ли способ отсортировать родительскую запись по самой ранней дате, связанной с ее дочерними записями?

У меня есть две таблицы, таблица счетов и таблица рабочих дней. Счета имеют много рабочих дней.

Схема рабочего дня имеет:

invoice_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

Я использую такой запрос: выберите * из рабочих дней внутреннего соединения счета-фактуры в рабочие дни.invoice_id = счет-фактура.id порядок рабочих дней.

Но могут быть счета-фактуры не по порядку, потому что порядок в счетах-фактурах не указан. Я не знаю другого способа указать порядок сортировки в счете-фактуре без кэширования самого раннего workday.date в родительском (счет-фактуре) в новом столбце, а затем сортировки по этому дополнительному столбцу.

Обновление: я использую postgres и mysql. Под «представлением» я не подразумеваю представление базы данных (материализованное), я имел в виду модель, представление, контроллер, уровень представления.

Вы должны использовать подзапрос exists с With, если вы повторно используете таблицу, для поиска max() даты, а также left для таких вещей, как «даже если в счете нет поля даты». Без данных, примеров и прочего сложно ответить.

phili_b 12.04.2019 08:24

Какой продукт СУБД вы используете? «SQL» — это просто язык запросов, а не название конкретного продукта базы данных. Добавьте ярлык для продукта базы данных, который вы используете postgresql, oracle, sql-server, db2, ...

a_horse_with_no_name 12.04.2019 08:26

Желаемый результат невозможен с представлением, так как каждая строка содержит разное количество столбцов. В реляционной базе данных таблица, представление или результат оператора SELECT всегда имеют одинаковое количество столбцов в каждой строке. И тип данных этого столбца фиксирован для всех строк.

a_horse_with_no_name 12.04.2019 08:28
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
3
41
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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)

Если вы хотите получить своих родителей-потомков за один обход сервера, используйте возможности 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, вам нужно вручную сделать запрос минимальным для сервера.

Если вы хотите полностью использовать возможности 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');

Другие вопросы по теме