简体   繁体   English

在两个表上查询一份报告(高级)

[英]Query on two tables for one report (Advanced)

I'm having some trouble with an advanced SQL query, and it's been a long time since I've worked with SQL databases. 我在使用高级SQL查询时遇到了一些麻烦,而且自从我处理SQL数据库以来已经很长时间了。 We use MySQL. 我们使用MySQL。

Background: 背景:

We will be working with two tables: 我们将使用两个表:

"Transactions Table" “交易表”

table: expire_history 表格: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 |       | 
+---------------+-----------------------------+------+-----+-------------------+-------+

"Information Table" “信息表”

table: information 表:信息

+---------------------+---------------+------+-----+---------------------+-------+
| 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   |       | 
+---------------------+---------------+------+-----+---------------------+-------+

We have a set of fields in one table that describe the record. 我们在一个表中有一组描述记录的字段。 Each record is comprised of a m_id (the person) and an ordinal (a person can have multiple records). 每个记录都由一个m_id(一个人)和一个序数(一个人可以有多个记录)组成。 So for instance, my m_id could be 1, and i could have multiple ordinals, (1, 2, 3, 4, etc), each with their own individual set of data. 因此,例如,我的m_id可以为1,而我可以具有多个序数(1、2、3、4等),每个序数都有各自独立的数据集。 The m_id and the m_a_ordinal comprise a composite key in the "information" table, and the m_id, m_a_ordinal, and a_expired_date fields in the "transactions" table comprises a composite key as well. m_id和m_a_ordinal在“信息”表中包含一个组合键,而“交易”表中的m_id,m_a_ordinal和a_expired_date字段也包含一个组合键。

Essentially when we expire a record, the a_state field in the information table is updated to expired. 本质上,当我们使一条记录过期时,信息表中的a_state字段将更新为过期。 At the same time, a record is created in the transactions table with the m_id, m_a_ordinal, and a_expired_date. 同时,将在事务表中创建带有m_id,m_a_ordinal和a_expired_date的记录。 We've found in the past that people get impatient and can click a button twice, so through some previous help I've managed to narrow down the most recent transaction for each expired record using the following query: 过去我们发现人们很不耐烦,可以单击两次按钮,因此通过先前的帮助,我设法使用以下查询缩小了每个过期记录的最新交易记录:

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;

Seems simple enough, right? 看起来很简单,对吧?

Let's add some complexity. 让我们增加一些复杂性。 Each record in the "information" table has a "natural expiration date" as well. “信息”表中的每个记录也都有一个“自然到期日”。 The original developer of our software, however, didn't code it to change the state of the record to "expired" once it's reached it's natural expiration date. 但是,我们软件的原始开发人员并未对它进行编码,以将记录的状态更改为“过期”,直到达到其自然过期日期。 It also does not write a transaction to the transaction table once it's expired (which I understand because this is only to keep records of ones that were expired by a person, as opposed to automagically). 一旦过期,它也不会将事务写入事务表中(我理解这是因为这只是为了保存一个人已过期的记录,而不是自动地)。 Also, when a record is expired manually, the original expiration date does not change. 此外,当记录手动过期时,原始过期日期不会更改。 This is why this is so complicated :P~~. 这就是为什么它如此复杂:P ~~。

Essentially I need to build a report that shows all aspects of expiration, whether it was expired manually, or naturally. 本质上,我需要构建一个报告,以显示到期的所有方面,无论是手动到期还是自然到期。

This report should take the data from the query above, and combines it with another query on the "information table" that says if a_expire_date <= CURDATE show record, except if record exisits in (query above from expire_history), then show record from (query on expire_history). 此报告应从上面的查询中获取数据,并将其与“信息表”上的另一个查询进行合并,该查询表明a_expire_date <= CURDATE显示记录,除非记录存在于(上面查询来自expire_history),然后显示来自(查询expire_history)。

a rough structure of the raw logic is as follows: 原始逻辑的大致结构如下:

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++

I hope that this is concise enough. 我希望这足够简洁。

Thanks for any help you can provide! 感谢您的任何帮助,您可以提供!

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;

Syntax may be off a bit don't ahve time to test; 语法可能有点不足,没有时间进行测试; but you can get the gist of it from this I hope: 但我希望您能从中得到要点:

Again what coalesce does is simply return the first NON-null value in a series of values. 同样,合并所做的只是简单地返回一系列值中的第一个NON-null值。 If you're only dealing with two NULLIF may work as well. 如果仅处理两个,则NULLIF也可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM