我在使用高级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++
我希望这很简洁。
感谢您提供的任何帮助!
答案 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也可以工作。