Снежинка получает предыдущее значение, которое было другим

У меня есть таблица, которая отслеживает местоположение по идентификатору, а также даты выпуска устройств и продукт/аксессуар, связанный с устройством. В локации одновременно может находиться только одно устройство, и устройство может время от времени получать новый аксессуар. Каждый раз, когда привязывается новый аксессуар, создается новая запись.
Я пытаюсь добавить к каждой записи информацию о предыдущем устройстве, если она была.

У меня есть таблица, как показано ниже:

ID_NO УСТРОЙСТВО_НЕТ DEVICE_DATE ПРОДУКТ НЕ PRODUCT_DATE ФД2А 600076 20 сентября 2011 г. 210785 03.01.2012 ФД2А 208049 11.09.2017 066762 11.09.2017 ФД2А 208049 11.09.2017 009802 2023-09-12 С600 202650 25 марта 2009 г. 127677 25 марта 2009 г. С600 215580 04.04.2012 127677 06.10.2010 С600 215580 04.04.2012 245791 10 апреля 2012 г. С600 215580 04.04.2012 366424 06.09.2013 С600 215580 04.04.2012 105547 2014-01-31 С600 215580 04.04.2012 503592 01.10.2015 С600 209855 2015-11-16 484106 09.10.2015 С600 600382 2020-08-24 347302 25 августа 2016 г.

Используя следующий запрос:

select
id_no
,device_no
,device_date
,product_no
,product_date
,lag(device_no) over (partition by id_no order by device_date, product_date) prev_device_no
,lag(device_date) over (partition by id_no order by device_date, product_date) prev_device_date
from device_data
order by id_no,device_date,product_date

Я получаю следующий результат:

ИД_НОТ УСТРОЙСТВО_НЕТ DEVICE_DATE ПРОДУКТ НЕ PRODUCT_DATE PREV_DEVICE_NO PREV_DEVICE_DATE ФД2А 600076 20 сентября 2011 г. 210785 03.01.2012 ФД2А 208049 11.09.2017 066762 11.09.2017 600076 20 сентября 2011 г. ФД2А 208049 11.09.2017 009802 2023-09-12 208049 11.09.2017 С600 202650 25 марта 2009 г. 127677 25 марта 2009 г. С600 215580 04.04.2012 127677 06.10.2010 202650 25 марта 2009 г. С600 215580 04.04.2012 245791 10 апреля 2012 г. 215580 04.04.2012 С600 215580 04.04.2012 366424 06.09.2013 215580 04.04.2012 С600 215580 04.04.2012 105547 2014-01-31 215580 04.04.2012 С600 215580 04.04.2012 503592 01.10.2015 215580 04.04.2012 С600 209855 2015-11-16 484106 09.10.2015 215580 04.04.2012 С600 600382 2020-08-24 347302 2016-08-25 209855 2015-11-16

Что я действительно хочу сделать, так это получить предыдущий номер устройства и дату, которые были другими: так:

ИД_НОТ УСТРОЙСТВО_НЕТ DEVICE_DATE ПРОДУКТ НЕ PRODUCT_DATE PREV_DEVICE_NO PREV_DEVICE_DATE ФД2А 600076 20 сентября 2011 г. 210785 03.01.2012 ФД2А 208049 11.09.2017 066762 11.09.2017 600076 20 сентября 2011 г. ФД2А 208049 11.09.2017 009802 2023-09-12 600076 20 сентября 2011 г. С600 202650 25 марта 2009 г. 127677 25 марта 2009 г. С600 215580 04.04.2012 127677 06.10.2010 202650 25 марта 2009 г. С600 215580 04.04.2012 245791 10 апреля 2012 г. 202650 25 марта 2009 г. С600 215580 04.04.2012 366424 06.09.2013 202650 25 марта 2009 г. С600 215580 04.04.2012 105547 2014-01-31 202650 25 марта 2009 г. С600 215580 04.04.2012 503592 01.10.2015 202650 25 марта 2009 г. С600 209855 2015-11-16 484106 09.10.2015 215580 04.04.2012 С600 600382 2020-08-24 347302 25 августа 2016 г. 209855 2015-11-16

есть ли другая функция для получения последнего другого значения при разделении?

Привет! Пожалуйста, отформатируйте свой вопрос так, чтобы его можно было прочитать: код как код, данные как таблицы и т. д.

NickW 07.06.2024 20:49

зафиксированный. извините, новичок в этом формате.

houayang 11.06.2024 18:03
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
2
77
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Думаю, у меня есть кое-что, что вам здесь подойдет. Я тестировал его только с первой группой данных, поэтому, возможно, потребуется настройка.

Что я делаю, так это беру вашу таблицу и нахожу все записи, которые различаются по device_no. Я предполагаю, что device_no не изменится, а затем вернется к предыдущему значению... Я думаю, это сломает это.

Как только это будет в data_delta CTE, я смогу выполнить asof соединение, чтобы получить предыдущую «запись изменения» для каждой записи, которая была у меня в исходной таблице.

Полный код выглядит так, но первый data CTE — это лишь некоторые примеры данных:

with data as (
    select *
    from (values('FD2A',600076,'2011-09-20'::date,'2012-01-03'::date),      
    ('FD2A',208049,'2017-09-11'::date,'2017-09-11'::date),
    ('FD2A',208049,'2017-09-11'::date,'2023-09-12'::date)
    ) x (id_no,device_no,device_date,product_date)
), data_delta as (
    select * from data
    qualify row_number() over (partition by id_no, device_no order by device_date, product_date) = 1
)
select d1.*
     , d2.device_no as prev_device_no
     , d2.device_date as prev_device_date
from data d1
asof join data_delta d2
  match_condition(d1.device_date > d2.device_date)
  on (d1.id_no = d2.id_no)
order by d1.product_date
  ;

Большое спасибо! Кажется, это работает для моей ситуации. Я попробую провести «стресс-тест».

houayang 11.06.2024 17:40

попробуйте использовать комбинацию LAG, CTE и CASE:

WITH DeviceHistory AS (
  SELECT 
    ID_NO,
    DEVICE_NO,
    DEVICE_DATE,
    PRODUCT_NO,
    PRODUCT_DATE,
    LAG(DEVICE_NO) OVER (PARTITION BY ID_NO ORDER BY DEVICE_DATE, PRODUCT_DATE) AS prev_device_no,
    LAG(DEVICE_DATE) OVER (PARTITION BY ID_NO ORDER BY DEVICE_DATE, PRODUCT_DATE) AS prev_device_date
  FROM your_table
),
FilteredHistory AS (
  SELECT
    ID_NO,
    DEVICE_NO,
    DEVICE_DATE,
    PRODUCT_NO,
    PRODUCT_DATE,
    CASE 
      WHEN prev_device_no IS NOT NULL AND prev_device_no != DEVICE_NO THEN prev_device_no
      ELSE NULL
    END AS prev_diff_device_no,
    CASE 
      WHEN prev_device_date IS NOT NULL AND prev_device_date != DEVICE_DATE THEN prev_device_date
      ELSE NULL
    END AS prev_diff_device_date,
    ROW_NUMBER() OVER (PARTITION BY ID_NO, DEVICE_NO ORDER BY DEVICE_DATE, PRODUCT_DATE) AS rn
  FROM DeviceHistory
)
SELECT
  ID_NO,
  DEVICE_NO,
  DEVICE_DATE,
  PRODUCT_NO,
  PRODUCT_DATE,
  prev_diff_device_no AS PREV_DEVICE_NO,
  prev_diff_device_date AS PREV_DEVICE_DATE
FROM FilteredHistory
QUALIFY 
  rn = 1 OR prev_diff_device_no IS NOT NULL
ORDER BY ID_NO, DEVICE_DATE, PRODUCT_DATE;

Похоже, что это фиксирует каждое местоположение и номер устройства, но только первое вхождение. поэтому он фиксирует, когда произошло изменение устройства, но мне все равно нужно видеть каждую запись, с которой был связан новый продукт. Спасибо за попытку.

houayang 11.06.2024 18:06

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