查询一个报告的两个表(高级)

时间:2011-11-22 19:13:13

标签: mysql sql join

我在使用高级SQL查询时遇到了一些麻烦,自从我使用SQL数据库以来已经有很长一段时间了。我们使用MySQL。

背景:

我们将使用两个表:

“交易表”

table: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)。

原始逻辑的粗略结构如下:

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 个答案:

答案 0 :(得分:1)

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-null值。如果你只处理两个NULLIF也可以工作。