Не удалось найти правильный SQL-запрос по требованию

У меня возникла проблема с поиском правильного SQL-запроса для моей программы. В основном мне приходится использовать две таблицы: Картон и Производство. У Cardboard есть Cardboard_Number, где последние 10 цифр обозначают номер накладной. Мне нужно найти запрос, который выбирает все продукты на основе входных данных PRODUCTION_NUMBER и POSNR, найти все номера накладных в производстве и, наконец, найти все продукты, в которых также использовался любой из номеров накладных. При поиске Произведений по номерам использованных накладных мне необходимо знать каждое Производство, в котором оно использовалось, независимо от того, когда и в какой строке оно использовалось.

У меня уже есть два запроса, которые почти выполняют мою работу, но я не уверен, как изменить и объединить их в один эффективный запрос, чтобы он соответствовал моим требованиям. (Запросы также включены в скрипт)

См. эту dbfiddle для примера данных, ожидаемого результата и более подробного описания.

Чтобы объяснить используемое «смещение»: в основном при поиске номера накладной я хочу получить все картоны, которые содержат этот номер + все картоны, которые были отсканированы до и после того, как каждый из них был найден на конкретной производственной линии. Более подробное объяснение смотрите в этой теме StackOverflow.

Редактировать:
Чтобы получить связь между производством и номером накладной, мне, по сути, нужно найти все картоны, отсканированные между Production_StartDT и Production_EndDT (я получаю начало и конец простым выбором, поскольку в качестве входных данных у меня есть PRODUCTION_NUMBER и POSNR). Как уже было сказано, последние 10 цифр Cardboard_Number обозначают номер накладной. Тогда мне пришлось бы найти все остальные Произведения, независимо от того, на какой производственной линии и независимо от начала и конца, в которых также использовался любой из номеров накладных.

Образец данных:

  • Производство:
| PRODUCTION_NUMBER | POSNR |      START_DT      |        END_DT      | PRODUCTION_LINE |
| -----------------:|------:|:-------------------|:-------------------|----------------:|
|       12344       |   1   | 28-FEB-24 14.02.35 | 29-FEB-24 18.02.35 |        2        |
|       12345       |   1   | 29-FEB-24 18.22.40 | 07-MAR-24 18.22.40 |        1        |
|       12345       |   2   | 05-MAR-24 13.02.35 | 12-MAR-24 13.02.35 |        2        |
|       12345       |   2   | 14-MAR-24 14.02.35 | 16-MAR-24 13.02.35 |        2        |

  • Картон:
| CARDBOARD_NUMBER |     DATE_TIME      | PRODUCTIONLINE_NUMBER |
| :----------------|:-------------------|----------------------:|
| WDL-005943998-1  | 05-AUG-14 10.03.32 |           1           |
| spL1ml82N4o      | 29-FEB-24 17.13.54 |           1           |
| WDL-005943998-1  | 01-MAR-24 09.44.42 |           1           |
| WDL-005943998-1  | 01-MAR-24 10.34.57 |           1           |
| 950024027237     | 01-MAR-24 10.44.57 |           1           |
| 950024027237     | 01-MAR-24 10.52.57 |           1           |
| WDL-005943998-1  | 01-MAR-24 13.58.43 |           2           |
| WDL-005943998-1  | 01-MAR-24 13.58.46 |           2           |
| spL1ml82N4o      | 01-MAR-24 14.09.43 |           2           |
| WDL-005943998-1  | 12-MAR-24 11.48.36 |           2           |

  • Текущий выбор для возврата продукции (со смещением) на основе ввода: номер накладной = 05943998-1:
    With Cardboard_offset(cardboard_number, date_time, productionline_number) as (
        select cardboard_number, date_time, productionline_number
        from (
            SELECT cardboard_number, date_time, productionline_number,
            sum(case when Cardboard_Number like CONCAT('%', '05943998-1') then 1 else 0 end) over (
                partition by ProductionLine_Number
                order by date_time
                rows BETWEEN 1 preceding AND 1 following
            ) matches
            from cardboard
        ) table1_with_matches
        where matches > 0
    )
    SELECT distinct p.production_number,
           p.posnr,
           p.production_line,
           p.start_dt,
           p.end_dt
    FROM   production p
           INNER JOIN cardboard_offset c
           ON p.production_line = c.productionline_number
           AND c.date_time BETWEEN p.start_dt AND p.end_dt
| PRODUCTION_NUMBER | POSNR | PRODUCTION_LINE |       START_DT     |       END_DT       |
| -----------------:|------:|----------------:|:-------------------|:-------------------|
| 12345             |   1   |        1        | 29-FEB-24 18.22.40 | 07-MAR-24 18.22.40 |
| 12345             |   2   |        2        | 05-MAR-24 13.02.35 | 12-MAR-24 13.02.35 |

  • Текущий выбор для возврата картонов (со смещением) на основе ввода: Production_number = 12345 и posnr = 1:
    select d.cardboard_number, d.date_time, d.productionline_number
    from production a
    join lateral
    (
        select cardboard_number, date_time, productionline_number
        from (
        SELECT cardboard_number, date_time, productionline_number,
            sum(case when date_time between a.start_dt and a.end_dt then 1 else 0 end) over (
                partition by ProductionLine_Number
                order by date_time
                rows BETWEEN 1 preceding AND 1 following
            ) matches
            from cardboard
        ) table1_with_matches
        where matches > 0
    ) d on a.production_line = d.productionline_number
    where a.production_number = 12345 and a.posnr = 1
| CARDBOARD_NUMBER |      DATE_TIME     | PRODUCTIONLINE_NUMBER |
| :----------------|:-------------------|----------------------:|
| spL1ml82N4o      | 29-FEB-24 17.13.54 |           1           |
| WDL-005943998-1  | 01-MAR-24 09.44.42 |           1           |
| WDL-005943998-1  | 01-MAR-24 10.34.57 |           1           |
| 950024027237     | 01-MAR-24 10.44.57 |           1           |
| 950024027237     | 01-MAR-24 10.52.57 |           1           |

  • Ожидаемый результат (с входными данными: PRODUCTION_NUMBER = 12345, POSNR = 1, смещение = 1):
12344 - 1 (because delivery note number 'pL1ml82N4o' was used in this production)
12345 - 1 (because delivery note numer '05943998-1' was used in this production)
12345 - 2 (because delivery note numer '05943998-1' was used in this production)

Привет! Все вопросы на этом форуме должны быть самодостаточными, поэтому, пожалуйста, не ссылайтесь на внешние сайты, которые содержат часть информации, необходимой для помощи вам (объяснение смещений); добавьте эту информацию в свой вопрос. Кроме того, в своем вопросе вы сказали «найти все номера накладных в производстве» - однако в таблице «Производство», похоже, нет ничего, что соответствовало бы номеру накладной, не могли бы вы объяснить это более подробно?

NickW 02.04.2024 13:08

@NickW Я обновил свой вопрос и добавил дополнительную информацию, надеюсь, она окажется для вас полезной.

philipp8230 02.04.2024 13:33
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
2
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я нашел решение:

SELECT distinct p.production_number,
           p.posnr,
           p.production_line,
           p.start_dt,
           p.end_dt
from Production production
join
(
    select d.cardboard_number, d.date_time, d.productionline_number
    from production a
    join lateral
    (
        select distinct SUBSTR(d.cardboard_number, -10), date_time
        from (
        SELECT cardboard_number, date_time, productionline_number,
            sum(case when date_time between a.start_dt and a.end_dt then 1 else 0 end) over (
                partition by ProductionLine_Number
                order by date_time
                rows BETWEEN 1 preceding AND 1 following
            ) matches
            from cardboard
        ) table1_with_matches
        where matches > 0
    ) d on a.production_line = d.productionline_number
    where a.production_number = 12345 and a.posnr = 1
) ca on ca.date_time between production.start_dt and production.end_dt;

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