从没有子查询的 MySQL 表中获取详细信息

Posted

技术标签:

【中文标题】从没有子查询的 MySQL 表中获取详细信息【英文标题】:Get the details from a MySQL table without sub query 【发布时间】:2017-10-26 12:55:17 【问题描述】:

我正在使用mysql 查询从 2 个表中获取数据。在这里,我在 table2 中有一个状态 Transfer Out。我确实需要获取状态为Transfer Out 的所有详细信息,同时,在Transfer Out 之后添加的Transfer In 状态不应该有任何详细信息。 这样我就不应该在Transfer Out 之后得到Transfer back In 的详细信息

现在我正在使用subquery。但是当数据计数变高时,就会导致超时问题。有没有更好的方法来重写查询并获得相同的结果?

我的查询示例是

SELECT  sq.etid
    FROM (
        SELECT  og.etid, pt.timestamp
            FROM  og_membership og
            INNER JOIN  table1 n ON(n.nid=og.etid)
            INNER JOIN  table2 pt ON(og.etid=pt.animal_nid)
            WHERE  og.entity_type='node'
              AND  pt.partner_gid = :gid
              AND  pt.shelter_gid = :our_gid
              AND  pt.type = 'Transfer Out'
              AND  (
                SELECT  count(id)
                    FROM  table2
                    WHERE  timestamp > pt.timestamp
                      AND  type = 'Transfer In'
                      AND  partner_gid = :gid
                      AND  shelter_gid = :our_gid
                   ) = 0
       ) AS sq 

【问题讨论】:

这不就是说最后一笔交易在哪里“转出”,或者转出后是否还有转入以外的交易? "来自 2 个表" -- 看起来像 3 个表! 【参考方案1】:

例如,您可以通过一个组来执行此操作

select something
from somehwere
group by something having isnull(max(out_date),0) > isnull(max(indate) ,0)

例如

DROP TABLE IF EXISTS LOANS;

CREATE TABLE LOANS (ID INT AUTO_INCREMENT PRIMARY KEY, ISBN INT,DIRECTION VARCHAR(3), DT DATETIME);

INSERT INTO LOANS(ISBN,DIRECTION,DT) VALUES
(1,'OUT','2017-10-01 09:00:00'),
(2,'OUT','2017-10-02 10:00:00'),
(2,'IN', '2017-10-02 10:10:00'),
(3,'REC','2017-10-02 10:00:00'),
(4,'REC','2017-10-02 10:00:00'),
(4,'OUT','2017-10-03 10:00:00'),
(4,'IN', '2017-10-04 10:00:00'),
(4,'OUT','2017-10-05 10:00:00')
;

SELECT ISBN
FROM   LOANS
WHERE  DIRECTION IN('OUT','IN') 
GROUP BY ISBN HAVING        
         MAX(CASE WHEN DIRECTION = 'OUT' THEN DT ELSE 0 END)  >
         MAX(CASE WHEN DIRECTION = 'IN'  THEN DT ELSE 0 END) ;

结果

+------+
| ISBN |
+------+
|    1 |
|    4 |
+------+
2 rows in set (0.00 sec)

如果 DT 出现平局,您可以替换 id。

【讨论】:

感谢您的努力。但问题是,没有像 out_date 和 indate 这样的字段。两者都有一个时间戳列,如果有摄入/结果,将添加新行 原理不变,请看例子补充回答。【参考方案2】:

改变

( SELECT COUNT(id) FROM ... ) = 0

EXISTS ( SELECT 1 FROM ... )

去掉最外层的查询和第一个pt.timestamp。 (或者pt.timestamp有什么不为人知的原因吗?)

table2 需要INDEX(type, partner_gid, shelter_gid, timestamp)timestamp 必须排在最后,但其他的可以任意排列。

table2 需要INDEX(type, partner_gid, shelter_gid, animal_nid);列可以按任何顺序排列。 (这个索引不能和前一个结合。)

og_membership 需要 INDEX(etid, entity_type)(以任意顺序)。

为什么查询中有INNER JOIN table1 n ON(n.nid=og.etid)table1 似乎根本没有被使用——除了可能用于验证行的存在。如果可能,请将其删除。

更改后,请提供EXPLAIN SELECT ...SHOW CREATE TABLE 用于2(或3??)表。

【讨论】:

以上是关于从没有子查询的 MySQL 表中获取详细信息的主要内容,如果未能解决你的问题,请参考以下文章

Mysql数据库一个表字段中存了id,并以逗号分隔,id对应的详细信息在另一个表中

在一个查询中从两个 mysql 表中选择数据

微信公众平台接口如何获取微信用户详细信息

加速超时的 MySQL 查询

比较并从同一个表中获取列详细信息

输入详细信息表时,我无法从主表中获取 ID(Laravel 8)