php - SQL查询优化建议

标签 php mysql

我遇到了一个奇怪的情况,几个 sql 查询+一些简单的 php 数学运算需要 30 秒+才能执行。我知道问题出在 sql 查询上,但我一辈子都想不出重写/优化查询的方法。

通常我会切换到联接,但因为它是带有数学的双子选择,所以我想不出更好的方法。我是否沿着正确的路线在查询中完成所有这一切,或者我应该做 4 个简单的计数选择并在 php 中完成所有数学运算。

索引建立在 where 子句中使用的所有列上。

查询 1

SELECT COUNT(1) FROM tblcontainergroups WHERE 
  (
        (SELECT COUNT(1) FROM tblmovements WHERE TicketStatus=1 AND MovementType=0 AND GroupID=tblcontainergroups.ID)
        -
        (SELECT COUNT(1) FROM tblmovements WHERE TicketStatus=1 AND MovementType=2 AND GroupID=tblcontainergroups.ID)
    )>0

查询 2

SELECT COUNT(1) FROM tblcontainergroups WHERE 
  (
        (SELECT COUNT(1) FROM tblmovements WHERE TicketStatus=1 AND MovementType=0 AND GroupID=tblcontainergroups.ID)
        -
        (SELECT COUNT(1) FROM tblmovements WHERE TicketStatus=1 AND MovementType=2 AND GroupID=tblcontainergroups.ID)
    )>0 AND LENGTH(DateOfIncreases)>4

那么 php 就是这 2 个数字的简单百分比

$percentage = number_format(($total_with_increases/$total_active_groups)*100,2);

我知道这可能是一个非常简单的问题,我可能是个白痴,但是有更好的方法吗?可以将查询重写得不那么慢吗?

表结构

--
-- Table structure for table `tblcontainergroups`
--

CREATE TABLE `tblcontainergroups` (
`ID` bigint(20) unsigned NOT NULL,
  `ContainerType` bigint(20) NOT NULL DEFAULT '0',
  `WasteType` bigint(20) NOT NULL DEFAULT '0',
  `IsHazardous` tinyint(1) NOT NULL DEFAULT '0',
  `PONumber` varchar(50) DEFAULT NULL,
  `SiteID` bigint(20) NOT NULL DEFAULT '0',
  `CreatedBy` int(10) NOT NULL DEFAULT '0',
  `CreatedOn` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `SICProducer` varchar(500) DEFAULT NULL,
  `HasRentals` tinyint(1) NOT NULL DEFAULT '0',
  `DistanceText` varchar(20) DEFAULT NULL,
  `DistanceMeters` int(10) NOT NULL DEFAULT '0',
  `IncreaseTrans` decimal(10,2) NOT NULL DEFAULT '0.00',
  `IncreaseTonnage` decimal(10,2) NOT NULL DEFAULT '0.00',
  `IncreaseWLHour` decimal(10,2) NOT NULL DEFAULT '0.00',
  `IncreasesCompleted` tinyint(1) NOT NULL DEFAULT '0',
  `DateOfIncreases` datetime DEFAULT NULL,
  `VariousWasteTypes` text,
  `PremRequired` tinyint(1) NOT NULL DEFAULT '0',
  `PremDescription` text
) ENGINE=InnoDB AUTO_INCREMENT=109454 DEFAULT CHARSET=latin1;

-- --------------------------------------------------------

--
-- Table structure for table `tblmovements`
--

CREATE TABLE `tblmovements` (
`ID` bigint(20) unsigned NOT NULL,
  `ClientID` bigint(20) unsigned NOT NULL,
  `SiteID` bigint(20) unsigned NOT NULL,
  `GroupID` bigint(20) NOT NULL DEFAULT '0',
  `PONumber` varchar(50) DEFAULT NULL,
  `MovementType` smallint(3) NOT NULL DEFAULT '0',
  `WLHours` decimal(6,2) NOT NULL DEFAULT '0.00',
  `Supplier` bigint(20) NOT NULL DEFAULT '0',
  `OrderedBy` varchar(200) DEFAULT NULL,
  `SupplierNotes` text,
  `DateRequired` datetime DEFAULT NULL,
  `SuppTransCharge` decimal(10,2) NOT NULL DEFAULT '0.00',
  `TransMarkup` decimal(10,2) NOT NULL DEFAULT '0.00',
  `TransClientCharge` decimal(10,2) NOT NULL DEFAULT '0.00',
  `SuppWeightRate` decimal(10,2) NOT NULL DEFAULT '0.00',
  `WeightMarkup` decimal(10,2) NOT NULL DEFAULT '0.00',
  `ClientWeightCharge` decimal(10,2) NOT NULL DEFAULT '0.00',
  `SupplierIncMinTonnes` decimal(10,2) NOT NULL DEFAULT '0.00',
  `ClientIncMinTonnes` decimal(10,2) NOT NULL DEFAULT '0.00',
  `TonnesClientCharge` decimal(10,2) NOT NULL DEFAULT '0.00',
  `TonneageType` smallint(3) NOT NULL DEFAULT '0',
  `SuppWLRate` decimal(10,2) NOT NULL DEFAULT '0.00',
  `WLMarkup` decimal(10,2) NOT NULL DEFAULT '0.00',
  `WLClientRate` decimal(10,2) NOT NULL DEFAULT '0.00',
  `CreatedBy` int(10) NOT NULL DEFAULT '0',
  `CreatedOn` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `TicketStatus` smallint(3) NOT NULL DEFAULT '1',
  `IsInvoiced` tinyint(1) NOT NULL DEFAULT '0',
  `GGOrderNumber` bigint(20) NOT NULL DEFAULT '0',
  `OrderSubmitted` tinyint(1) NOT NULL DEFAULT '0',
  `ParentTicket` bigint(20) unsigned NOT NULL DEFAULT '0',
  `SuppWLHours` decimal(5,2) NOT NULL DEFAULT '0.00',
  `ClientWLHours` decimal(5,2) NOT NULL DEFAULT '0.00',
  `WasteDestination` int(10) NOT NULL DEFAULT '0',
  `TicketWeight` decimal(10,4) NOT NULL DEFAULT '0.0000',
  `VHCReg` varchar(10) DEFAULT NULL,
  `SupplierContact` varchar(200) DEFAULT NULL,
  `ComplianceNotes` text,
  `WeightAddedBy` int(10) NOT NULL DEFAULT '0',
  `RateSetBy` int(10) NOT NULL DEFAULT '0',
  `IsCompleted` tinyint(1) NOT NULL DEFAULT '0',
  `DateWeightAdded` datetime DEFAULT NULL,
  `RebateRate` decimal(10,2) NOT NULL DEFAULT '0.00',
  `InvoiceNumber` varchar(50) DEFAULT NULL,
  `IsPaid` tinyint(1) NOT NULL DEFAULT '0',
  `InvoiceDate` datetime DEFAULT NULL,
  `ActualRebate` decimal(20,2) NOT NULL DEFAULT '0.00',
  `RebateToClient` decimal(10,2) NOT NULL DEFAULT '0.00',
  `SupplierWeightContact` varchar(200) DEFAULT NULL,
  `VHCAddedBy` int(10) NOT NULL DEFAULT '0',
  `OldTicketNumber` varchar(20) DEFAULT NULL,
  `BelongsToWR` bigint(20) NOT NULL DEFAULT '0',
  `OkInvoice` tinyint(1) NOT NULL DEFAULT '0',
  `DeletionDate` datetime DEFAULT NULL,
  `DeletedBy` int(10) NOT NULL DEFAULT '0',
  `SupplierInvNo` varchar(100) DEFAULT NULL,
  `SuppTicketNo` varchar(100) DEFAULT NULL,
  `SuppIsDisputed` tinyint(1) NOT NULL DEFAULT '0',
  `SuppDateDisputed` datetime DEFAULT NULL,
  `SuppDisputedBy` int(10) NOT NULL DEFAULT '0',
  `SuppDateDisputeCleared` datetime DEFAULT NULL,
  `SuppDisputeClearedBy` int(10) NOT NULL DEFAULT '0',
  `SuppIsPaid` tinyint(1) NOT NULL DEFAULT '0',
  `SuppPaidOn` datetime DEFAULT NULL,
  `SuppPaidBy` int(10) NOT NULL DEFAULT '0',
  `TicketApproveReason` text,
  `ComplianceCopyTicket` tinyint(1) NOT NULL DEFAULT '0',
  `SuppInvCheckedBy` int(10) NOT NULL DEFAULT '0',
  `SuppCheckDate` datetime DEFAULT NULL,
  `SupplierOrderConfirmedBy` text,
  `OrderConfirmationDate` datetime DEFAULT NULL,
  `OrderConfirmedUser` int(10) NOT NULL DEFAULT '0',
  `TicketReceived` tinyint(1) NOT NULL DEFAULT '0',
  `DisputeReason` text,
  `DisputeType` smallint(5) NOT NULL DEFAULT '0',
  `DisputeClearReason` text,
  `ClientIsDisputed` tinyint(1) NOT NULL DEFAULT '0',
  `ClientDateDisputed` datetime DEFAULT NULL,
  `ClientDisputedBy` int(10) NOT NULL DEFAULT '0',
  `ClientDisputeReason` text,
  `ClientDisputeType` smallint(5) NOT NULL DEFAULT '0',
  `ClientDateDisputeCleared` datetime DEFAULT NULL,
  `ClientDisputeClearedBy` int(10) NOT NULL DEFAULT '0',
  `ClientDisputeClearReason` text,
  `CarbonUsageKGKM` decimal(20,4) NOT NULL DEFAULT '0.0000',
  `CarbonUsageKGL` decimal(20,4) NOT NULL DEFAULT '0.0000',
  `SuppTonneageType` smallint(3) NOT NULL DEFAULT '0',
  `TicketApprovedBy` int(10) NOT NULL DEFAULT '0',
  `TicketApprovedDate` datetime DEFAULT NULL,
  `IsLate` tinyint(1) NOT NULL DEFAULT '0',
  `RoRoProcessed` tinyint(1) NOT NULL DEFAULT '0',
  `LeadOwnerBDM` int(10) NOT NULL DEFAULT '0',
  `LastComplianceUpdate` datetime DEFAULT NULL,
  `IsDummy` tinyint(4) DEFAULT '0',
  `DisputerName` text,
  `DisputerContact` text,
  `ClientDisputerName` text,
  `ClientDisputerContact` text,
  `MarginsProcessed` tinyint(1) NOT NULL DEFAULT '0',
  `OrigCreator` int(10) NOT NULL DEFAULT '0',
  `AccountsSent` tinyint(1) NOT NULL DEFAULT '0',
  `NoRebate` tinyint(1) NOT NULL DEFAULT '0',
  `WTNCreated` tinyint(1) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=368401 DEFAULT CHARSET=latin1;

--
-- Indexes for dumped tables
--

--
-- Indexes for table `tblcontainergroups`
--
ALTER TABLE `tblcontainergroups`
 ADD PRIMARY KEY (`ID`), ADD KEY `ContainerType` (`ContainerType`), ADD KEY `WasteType` (`WasteType`);

--
-- Indexes for table `tblmovements`
--
ALTER TABLE `tblmovements`
 ADD PRIMARY KEY (`ID`), ADD KEY `ClientID` (`ClientID`), ADD KEY `SiteID` (`SiteID`), ADD KEY `GroupID` (`GroupID`), ADD KEY `Supplier` (`Supplier`), ADD KEY `OrderedBy` (`OrderedBy`), ADD KEY `CreatedBy` (`CreatedBy`), ADD KEY `GGOrderNumber` (`GGOrderNumber`), ADD KEY `WasteDestination` (`WasteDestination`), ADD KEY `WeightAddedBy` (`WeightAddedBy`), ADD KEY `RateSetBy` (`RateSetBy`), ADD KEY `VHCAddedBy` (`VHCAddedBy`), ADD KEY `BelongsToWR` (`BelongsToWR`), ADD KEY `DeletedBy` (`DeletedBy`), ADD KEY `SupplierInvNo` (`SupplierInvNo`), ADD KEY `SuppDisputedBy` (`SuppDisputedBy`), ADD KEY `SuppDisputeClearedBy` (`SuppDisputeClearedBy`), ADD KEY `SuppPaidBy` (`SuppPaidBy`), ADD KEY `SuppInvCheckedBy` (`SuppInvCheckedBy`), ADD KEY `OrderConfirmedUser` (`OrderConfirmedUser`), ADD KEY `DisputeType` (`DisputeType`), ADD KEY `TicketApprovedBy` (`TicketApprovedBy`), ADD KEY `ClientDisputeClearedBy` (`ClientDisputeClearedBy`), ADD KEY `ClientDisputedBy` (`ClientDisputedBy`), ADD KEY `LeadOwnerBDM` (`LeadOwnerBDM`), ADD KEY `m_disputed` (`SuppIsDisputed`), ADD KEY `m_clientdisputed` (`ClientIsDisputed`), ADD KEY `OrigCreator` (`OrigCreator`), ADD KEY `TicketStatus` (`TicketStatus`), ADD KEY `MovementType` (`MovementType`);

最佳答案

这可能是一个简单的问题,但是对我来说很难,因为我看不到您正在尝试构建的模型逻辑。

不过,根据我的说法,以下应该是您的查询的优化版本:

SELECT COUNT(1) 
FROM tblcontainergroups 
WHERE (SELECT SUM(IF(MovementType=0,1,IF(MovementType=2, -1, 0)))
    FROM tblmovements 
    WHERE GroupID=tblcontainergroups.ID AND TicketStatus=1)>0

基本上,您只需要一个带有条件 SUM 的子查询,该子查询将根据 MovementType 值求和 1 或 -1,以及 GroupID 和 TicketStatus 子查询的条件。

此外,您还需要为 tblmovements 表中的 GroupID、MovementType 和 TicketStatus 字段(分别)创建索引。

关于php - SQL查询优化建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35222261/

相关文章:

Mysql 选择在给定日期范围内多次出现的项目

php - 您的 SQL 语法有误;查看与您的 MySQL 服务器版本对应的手册,了解在 '' 附近使用的正确语法

php - 在字符串末尾查找最长的字典单词

php - 发布类别将复选框值插入数据库

php - JavaScript 促进了 OpenID 登录?

php - 查询结果存入变量

javascript - 将值从 javascript 插入数据库

mysql - SQL:仅从大型数据集中获取采样数据

php - 在mysql中保存图像名称?

java - com.mysql.jdbc.exceptions.jdbc4.CommunicationsException : Communications link failure AND BeanEntityManager error