0

MySQL 问题。

我有一份合同和订单文件。标准的父母和孩子 - 一对多的关系。一份合约可以有很多订单。公共连接字段是 c_contract_id = co_contract_id。

合同具有限定合同的 c_type_code,订单也具有 co_order_type_code。

我正在构建一个通用搜索,允许用户根据许多字段进行选择。给我带来麻烦的查询是在 contract 或 contract_orders 表中查找具有特定 type_code 的那些合约的 contract_ids。

表中有许多字段可供用户搜索。我的问题的相关领域是:

CREATE TABLE `ndx_contracts` (
  `c_contract_id` int(11) NOT NULL AUTO_INCREMENT,
  `c_type_code` char(2) NOT NULL,
  PRIMARY KEY (`c_contract_id`),
  KEY `c_type_code` (`c_type_code`)
) ENGINE=InnoDB AUTO_INCREMENT=1


CREATE TABLE `ndx_contract_orders` (
  `co_contract_id` int(11) NOT NULL,
  `co_contract_orderid` int(11) NOT NULL AUTO_INCREMENT,
  `co_order_type_code` varchar(2) NOT NULL,
  `co_data` varchar(255),
  PRIMARY KEY (`co_contract_orderid`,`co_contractid`),
  KEY `co_order_type_code` (`co_order_type_code`)
) ENGINE=InnoDB AUTO_INCREMENT=1


SELECT count(1)
FROM contracts
WHERE 
    c_type_code IN ('02')
        OR (
               (SELECT count(co_order_type_code) FROM contract_orders
                    WHERE
                        co_contract_id = c_contract_id
                        AND co_order_type_code IN ('02')
               ) > 0
           )
;    

此查询有效,但速度非常慢。我只有大约 40,000 份合约,每份都有大约 4 条订单记录,搜索需要 311 秒才能返回 320 秒的行。

我会做一个外连接,但这会返回许多额外的行。

谢谢你

4

1 回答 1

1

听起来你想计算不同的合同 ID,所以这应该为你做。

SELECT COUNT(DISTINCT c.c_contract_id) AS `contract_id_count`
FROM ndx_contracts AS c
LEFT OUTER JOIN ndx_contract_orders AS co
  ON c.c_contract_id = co.co_contract_id
WHERE c.c_type_code = ? OR co.co_order_type_code = ?

请注意,这将允许合同没有订单的情况。?显然会用您的搜索值替换。如果您想要实际的订单 ID,只需删除COUNT()选择中的功能。

你的主键ndx_contract_orders实际上是一个问题。要执行此连接,您仅通过 contract_id 查找,您需要反转该主索引的字段顺序,以便能够仅通过 contract_id 启用索引查找。或者,您可以只为co_contract_id. 老实说,如果订单 id 是自动增量,则该字段本身可能应该是您的主键,并且该co_contract_id字段应该只有它自己的索引。无需在两个字段中强制使用唯一索引,因为 order_id 上的主键自动增量将确保唯一性。

于 2013-04-09T20:25:07.707 回答