Как отобразить данные по области для следующей постановки задачи? - PullRequest
1 голос
/ 13 февраля 2020

У меня следующая структура таблицы

Area    Section    Carrying_Engine

A1        S1           Petrol
A2        S1           Petrol
A3        S1           Diesel
A4        S1           Petrol
A5        S2           Diesel
A6        S2           Petrol

Формулировка проблемы заключается в том, что мы должны отобразить, в какой области В соответствии с разделами S1 и S2, перевозимый двигатель был бензиновым и дизельным, выходной должен быть

Section   From_Area   To_Area   Carrying_Engine

S1          A1          A3         Petrol
S1          A3          A4         Diesel
S1          A4          A5         Petrol
S2          A5          A6         Diesel 

PS: Везде, где у нас есть переход в любом из двигателей или разделов, стоимость переноса добавляется к предыдущему счету раздела или двигателя, например, в 3-м ряду происходит переход, поэтому здесь, пока мы перемещаемся из A2 в A3 мы использовали бензиновый двигатель, а в точке A3 мы подключили дизельный двигатель, и поэтому в разделе S1 мы переместили бензиновый двигатель из зоны A1 в A3. Аналогичным образом, в 4-5-м ряду мы переходим из секции S1 в S2, используя бензиновый двигатель и подключенный дизельный двигатель в точке A5, но здесь мы добавляем транспортные расходы только к счету секции S1, поэтому из области A4 в A5 мы использовали бензиновый двигатель в разделе S1.

Я не могу получить логи c, чтобы решить эту проблему, пожалуйста, руководство.

Ответы [ 2 ]

1 голос
/ 13 февраля 2020

Всякий раз, когда секция или двигатель изменяют, отмечают строку с флагом 1, иначе 0.

case when lag(carrying_engine) over (order by area) = carrying_engine 
      and lag(section) over (order by area) = section 
     then 0 else 1 end as flag

Затем суммируйте эти флаги по порядку.

sum(flag) over (order by a) grp

Это назначит каждую строку группе. Теперь легко, найдите минимальную область и минимальную область из следующего ряда.

min(a) a1, lead(min(a)) over (order by grp) a2

Вы можете удалить последний ряд, который вам не нужен, используя

where a2 is not null

Вместе:

with 
  groups as (
    select a, s, e, sum(flag) over (order by a) grp
      from (
        select area a, Section s, Carrying_Engine e,
               case when lag(carrying_engine) over (order by area) = carrying_engine 
                     and lag(section) over (order by area) = section 
                    then 0 else 1 end as flag
          from engines))
select * 
  from (
    select s, e, grp, min(a) a1, lead(min(a)) over (order by grp) a2
      from groups group by s, e, grp ) 
  where a2 is not null
  order by grp

dbfiddle

Я использовал area, чтобы определить порядок строк, потому что это все, что вы указали, но если Ваша таблица содержит другой идентификатор, используйте его в order by предложениях.

1 голос
/ 13 февраля 2020

Вы можете воспользоваться аналитической функцией , но я должен сказать, что у вас должен быть какой-то столбец для определения порядка столбцов, поскольку oracle не обеспечивает автоматического c упорядочения записей.

Я использовал столбец DATETIME, чтобы определить порядок столбца в следующем решении:

SQL> WITH YOUR_TABLE (Area,    Section,    Carrying_Engine, DATETIME) AS
  2  (SELECT 'A1',        'S1',           'Petrol', SYSDATE - 6 FROM DUAL UNION ALL
  3  SELECT 'A2',        'S1',           'Petrol', SYSDATE - 5 FROM DUAL UNION ALL
  4  SELECT 'A3',        'S1',           'Diesel', SYSDATE - 4 FROM DUAL UNION ALL
  5  SELECT 'A4',        'S1',           'Petrol', SYSDATE - 3 FROM DUAL UNION ALL
  6  SELECT 'A5',        'S2',           'Diesel', SYSDATE - 2 FROM DUAL UNION ALL
  7  SELECT 'A6',        'S2',           'Petrol', SYSDATE - 1 FROM DUAL)
  8  SELECT * -- your query starts from here
  9  FROM
 10      (
 11          SELECT
 12              SECTION,
 13              AREA   AS FROM_AREA,
 14              LEAD(AREA) OVER(ORDER BY DATETIME ) AS TO_AREA,
 15              CARRYING_ENGINE
 16          FROM
 17              (
 18                  SELECT
 19                      T.*,
 20                      LAG(CARRYING_ENGINE) OVER(ORDER BY DATETIME) AS LEAD_CARRYING_ENGINE
 21                  FROM YOUR_TABLE T
 22              )
 23          WHERE LEAD_CARRYING_ENGINE <> CARRYING_ENGINE
 24              OR LEAD_CARRYING_ENGINE IS NULL
 25      )
 26  WHERE TO_AREA IS NOT NULL;

SECTION | FROM_AREA | TO_AREA | CARRYING_ENGINE
------- | --------- | ------- | ---------------
S1      | A1        | A3      | Petrol
S1      | A3        | A4      | Diesel
S1      | A4        | A5      | Petrol
S2      | A5        | A6      | Diesel

Cheers !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...