Запрос двух таблиц для одного отчета (расширенный) - PullRequest
1 голос
/ 22 ноября 2011

У меня возникли проблемы с расширенным запросом SQL, и я давно не работал с базами данных SQL.Мы используем MySQL.

Справочная информация:

Мы будем работать с двумя таблицами:

«Таблица транзакций»

таблица:expire_history

+---------------+-----------------------------+------+-----+-------------------+-------+    
| Field         | Type                        | Null | Key | Default           | Extra |
+---------------+-----------------------------+------+-----+-------------------+-------+
| m_id          | int(11)                     | NO   | PRI | 0                 |       | 
| m_a_ordinal   | int(11)                     | NO   | PRI | 0                 |       | 
| a_expired_date| datetime                    | NO   | PRI |                   |       | 
| a_state       | enum('EXPIRED','UNEXPIRED') | YES  |     | NULL              |       | 
| t_note        | text                        | YES  |     | NULL              |       | 
| t_updated_by  | varchar(40)                 | NO   |     |                   |       | 
| t_last_update | timestamp                   | NO   |     | CURRENT_TIMESTAMP |       | 
+---------------+-----------------------------+------+-----+-------------------+-------+

«Информационная таблица»

таблица: информация

+---------------------+---------------+------+-----+---------------------+-------+
| Field               | Type          | Null | Key | Default             | Extra |
+---------------------+---------------+------+-----+---------------------+-------+
| m_id                | int(11)       | NO   | PRI | 0                   |       | 
| m_a_ordinal         | int(11)       | NO   | PRI | 0                   |       | 
| a_type              | varchar(15)   | YES  | MUL | NULL                |       | 
| a_class             | varchar(15)   | YES  | MUL | NULL                |       | 
| a_state             | varchar(15)   | YES  | MUL | NULL                |       | 
| a_publish_date      | datetime      | YES  |     | NULL                |       | 
| a_expire_date       | date          | YES  |     | NULL                |       | 
| a_updated_by        | varchar(20)   | NO   |     |                     |       | 
| a_last_update       | timestamp     | NO   |     | CURRENT_TIMESTAMP   |       | 
+---------------------+---------------+------+-----+---------------------+-------+

В одной таблице есть набор полей, которые описываютзапись.Каждая запись состоит из m_id (человек) и порядкового номера (человек может иметь несколько записей).Так, например, мой m_id может быть 1, и у меня может быть несколько порядковых чисел (1, 2, 3, 4 и т. Д.), Каждый со своим индивидуальным набором данных.M_id и m_a_ordinal содержат составной ключ в таблице «информации», а поля m_id, m_a_ordinal и a_expired_date в таблице «транзакции» также содержат составной ключ.

По существу, когда мы истекаем запись, поле a_state в информационной таблице обновляется до истекшего.В то же время в таблице транзакций создается запись с m_id, m_a_ordinal и a_expired_date.В прошлом мы обнаружили, что люди теряют терпение и могут дважды нажать кнопку, поэтому с помощью предыдущей справки мне удалось сузить самую последнюю транзакцию для каждой просроченной записи, используя следующий запрос:

SELECT e1.m_id, e1.m_a_ordinal, e1.a_expired_date, e1.t_note, e1.t_updated_by 
FROM expire_history e1 
    INNER JOIN  (SELECT m_id, m_a_ordinal, MAX(a_expired_date) AS a_expired_date 
    FROM expire_history GROUP BY m_id, m_a_ordinal) e2 
    ON (e2.m_id = e1.m_id AND e2.m_a_ordinal = e1.m_a_ordinal AND e2.a_expired_date = e1.a_expired_date) 
WHERE e2.a_expired_date > '2008-05-15 00:00:00' ORDER BY a_date_expired;

Кажется достаточно простым, верно?

Давайте добавим немного сложности.Каждая запись в «информационной» таблице также имеет «естественную дату истечения».Первоначальный разработчик нашего программного обеспечения, однако, не кодировал его, чтобы изменить состояние записи на «истек», как только она достигла своей естественной даты истечения срока действия.Он также не записывает транзакцию в таблицу транзакций после истечения срока ее действия (что я понимаю, потому что это только для того, чтобы вести записи тех, срок действия которых истек человеком, а не автоматически).Кроме того, когда срок действия записи истек вручную, исходная дата истечения срока не изменяется.Вот почему это так сложно: P ~~.

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

Этот отчет должен взять данные из запроса выше и объединить их сдругой запрос к «информационной таблице», который говорит, что если a_expire_date <= CURDATE показать запись, кроме случаев, когда запись существует в (запрос выше из expire_history), то показать запись из (запрос по expire_history).</p>

Грубая структура необработанной логики выглядит следующим образом:

for x in record_total
   if (m_id m_a_ordinal) exists in expire_history
      display m_id, m_a_ordinal, a_expired_date, a_state)
   else if (m_id_a_ordinal) exists in information AND a_expire_date <= CURDATE
      display (m_id, m_a_ordinal, a_expire_date, a_state)
   end if
x++

Я надеюсь, что это достаточно кратко.

Спасибо за любую помощь, которую вы можете оказать!

1 Ответ

1 голос
/ 23 ноября 2011
SELECT i.m_id, I.m_a_ordinal, 
   coalesce(e1.a_expired_date, I.A_Expire_Date) as Expire_DT, 
   coalesce(e1.t_note,'insert related item column'),
   coalesce(e1.t_updated_by, I.A_Updated_by) as Updated_By
FROM Information I 
    LEFT JOIN expire_history e1 
      ON E1.M_ID = I.M_ID
      AND I.m_a_ordinal=e1.M_a_ordinal
    INNER JOIN  
       (SELECT m_id, m_a_ordinal, MAX(a_expired_date) AS a_expired_date 
        FROM expire_history GROUP BY m_id, m_a_ordinal) e2 
      ON (e2.m_id = e1.m_id 
      AND e2.m_a_ordinal = e1.m_a_ordinal 
      AND e2.a_expired_date = e1.a_expired_date) 
WHERE coalesce(e2.a_expired_date,i.A_Expire_Date) > '2008-05-15 00:00:00' 
ORDER BY a_date_expired;

Синтаксис может быть отключен, не время проверять;но вы можете понять суть этого, я надеюсь:

Опять же, что делает coalesce, это просто возвращает первое NON-нулевое значение в серии значений.Если вы имеете дело только с двумя, NULLIF также может работать.

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