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

#sql #oracle

#sql #Oracle

Вопрос:

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

У меня есть 3 таблицы.

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

Мне нужно получить ПОСЛЕДНЮЮ дату обновления (временную метку) для определенного номера продукта (может быть более одного продукта), какой статус для него.

Вот как выглядят таблицы (они намного сложнее, но я их упростил)

 mercury.cs_batch_event
PRODUCT_ID (VARCHAR2(100 CHAR))
CBL_REQUEST_ID (VARCHAR2(12 CHAR))

mercury.cs_status_srch
CBL_REQUEST_ID (VARCHAR2(12 CHAR))
LOG_ID  (VARCHAR2(12 CHAR))
STATUS_REF_ID (NUMBER(8,0))

mercury.edit_log
ELOG_ID (VARCHAR2(12 CHAR))
ON_DATE_TIME (TIMESTAMP(6))
  

Я попытался сделать это несколькими разными способами, и после некоторого поиска в Интернете, ближе всего я мог добраться до этого:

 SELECT * 
FROM (SELECT cbl.product_id, src.status_ref_id,
             TO_CHAR(elog.on_date_time, 'dd/mm/yyyy hh24:mi:ss') date_updated
      FROM mercury.cs_batch_event cbl,
           mercury.cs_status_srch src, 
           mercury.edit_log elog
      WHERE cbl.product_id IN ('A555', 'B555')
        AND cbl.cbl_request_id = src.cbl_request_id
        AND src.log_id = elog.elog_id
      ORDER BY elog.on_date_time DESC)
WHERE rownum = 1
  

И он вернулся ниже, что правильно, но когда вставляется несколько номеров продуктов, он по-прежнему возвращает значение только для одного продукта (что связано с row number=1 вероятностью)

 PRODUCT_NUMBER  DATE_UPDATED        STATUS
A555            29/06/2011 07:51:24 30169
  

Спасибо

Комментарии:

1. Хорошо, можем ли мы получить некоторые образцы начальных данных для этого? Набор ответов потенциально большой, потому что у вас может быть много-много связей, о которых вы нам не рассказали

Ответ №1:

Это должно сделать это:

 SELECT 
  t1.product_number, 
  t2.status, 
  TO_CHAR (t3.update_time, 'dd/mm/yyyy hh24:mi:ss') date_updated,
FROM 
  batch_event t1, 
  status_srch t2, 
  edit_log t3
WHERE 
  t1.product_number in ('A555', 'B555')
  AND t1.ID_1 = t2.ID_1
  AND t2.ID_2 = t3.ID_2
  AND t3.update_time = (SELECT max(update_time) 
                        FROM edit_log 
                        WHERE ID_2 = t3.ID_2)
  

Ах, думаю, я неправильно понял ваши данные.. Попробуйте это вместо:

 SELECT 
  t1.product_number,
  t2.status,
  t3.update_time
FROM 
  batch_event t1, 
  status_srch t2, 
  edit_log t3,
(
    SELECT 
      batch_event.product_number product_number, 
      max(edit_log.update_time) maxupdatetime,
    FROM 
      batch_event, 
      status_srch, 
      edit_log
    WHERE 
      batch_event.ID_1 = status_srch.ID_1
      AND status_srch.ID_2 = edit_log.ID_2
    GROUP BY
      batch_event.product_number
) t4
WHERE t1.ID_1 = t2.ID_1
AND t2.ID_2 = t3.ID_2
AND t1.product_number = t4.product_number
AND t3.update_time = t4.maxupdatetime
  

Комментарии:

1. Приветствую, что теперь у вас все получится!

2. Похоже, это не сработало для меня, поскольку дало мне все обновленные времена для этого продукта.

3. Я обновил свои исходные таблицы и sql до того, что мы на самом деле имеем в базе данных, поскольку я путался с ними, и мне потребовалось некоторое время, чтобы переименовать все это!

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

5. Эй, Стиви, выше работает так, как я этого хотел! Большое вам спасибо за помощь! очень признателен!!!!!!

Ответ №2:

Может быть хорошим примером для аналитических функций

 SELECT product_id,
       status_ref_id,
       TO_CHAR(on_date_time, 'dd/mm/yyyy hh24:mi:ss')
FROM (SELECT cbl.product_id,
             src.status_ref_id,
             elog.on_date_time,
             ROW_NUMBER() OVER (PARTITION BY cbl.product_id ORDER BY on_date_time DESC)
               AS ordered_by_recency
      FROM mercury.cs_batch_event cbl,
           mercury.cs_status_srch src, 
       mercury.edit_log elog
      WHERE cbl.product_id IN ('A555', 'B555')
        AND cbl.cbl_request_id = src.cbl_request_id
        AND src.log_id = elog.elog_id) d
WHERE ordered_by_recency = 1
  

Комментарии:

1. Эй, Пилкроу, спасибо за вашу помощь, но я уже получил ее от запроса Стиви!

2. @Грег, я рад. Также не помешает иметь больше, чем правильный способ сделать это. 🙂

3. Безусловно, я все равно рассмотрю это, сейчас на меня просто немного давит время, чтобы получить все, что мне нужно! Спасибо!

Ответ №3:

Попробуйте это:

 SELECT t1.product_number, t2.status,
    (SELECT Update_Time FROM Edit_log el
     INNER JOIN Status_srch ss ON el.ID_2 = ss.ID_2
     INNER JOIN Batch_event be ON ss.ID_1 = be.ID_1
     WHERE be.Product Number = t1.product_number
           AND RowNum<=1
     ORDER BY Update_Time DESC) AS date_updated
FROM Batch_event t1 
INNER JOIN Status_srch t2 ON t1.ID_1 = t2.ID_1
WHERE t1.product_number in ('A555', 'B555')
  

Комментарии:

1. Спасибо за это, я думаю, что я попробовал что-то подобное с SELECT TOP 1, и это выдало мне ошибку!

2. Похоже, что он не работает, поскольку я получаю ошибку пропущенного выражения.

3. @Greg: попробуйте мой новый код… Я написал (Код продукта) вместо product_code. Попробуйте и дайте мне знать

4. Спасибо, Марко, проблема была не в Product_code, это смущает, но я не думаю, что использую SQL server! Это может быть причиной того, что он не работает!

5. @Greg: Вы используете MySQL? Postgres? Oracle? Попробуйте угадать и дайте мне знать. Какую ошибку вы получаете сейчас?