gpt4 book ai didi

mysql - 使用子选择和 IF 条件的缓慢 MySQL 查询

转载 作者:行者123 更新时间:2023-11-29 06:51:38 24 4
gpt4 key购买 nike

我遇到了一些小问题,希望得到一些建议。
我想要做的是从 tableA 中选择所有内容,其中 tableB 中有一个条目,其中 tableB 中的条目是表中的第一个条目,并且该条目在特定日期范围内。

所以开始日期为 2013-01-01 00:00:00 结束日期为 2013-01-31 23:59:59 我需要做这样的事情

SELECT * FROM tblsites WHERE ID IN(SELECT 
IF(DateRequired >= '2013-01-01 00:00:00' AND DateRequired <= '2013-01-31 23:59:59', SiteID, '' ) AS SiteID FROM `tblmovements` WHERE TicketStatus IN ( 0, 1 ) GROUP BY SiteID) AND LENGTH(SiteName)>0 ORDER BY SiteName ASC

基本上,它应该返回一个网站数据列表,其中该网站在所选日期范围内进行了首次移动。 DateRequired 列是我在 tblmovements 中的移动日期,tblmovements 将 SiteID 存储为一列。您可以忽略票证状态,它只是一个标志,表示票证处于事件状态,它不应该在查询中产生结果。

所以我的理论是,如果我在 tblmovements 中选择它们处于事件状态的所有票证并将它们分组在 siteid 上,那么如果 DateRequired 在我的输入日期之间,那么我可以让子查询只返回站点 ID,这将允许我在站点表上做一个简单的 SELECT WHERE IN()。 LENGTH 子句只是因为 if 在 else 子句上返回零长度,所以我不想在脚本中过滤掉它,而是想在查询时过滤掉它们。

查询运行没有错误,但速度绝对慢得要命(30 分钟以上,而且还在运行)叫醒我将不胜感激。
如果您能理解我上面的漫无边际的话,用更好的方式完整地编写它也很好。

编辑:虚拟表。

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

CREATE TABLE IF NOT EXISTS `tblmovements` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`SiteID` bigint(20) unsigned NOT NULL,
`TicketStatus` smallint(3) NOT NULL DEFAULT '1',
`DateRequired` datetime DEFAULT NULL,
PRIMARY KEY (`ID`),
KEY `SiteID` (`SiteID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;

--
-- Dumping data for table `tblmovements`
--

INSERT INTO `tblmovements` (`ID`, `SiteID`, `TicketStatus`, `DateRequired`) VALUES
(1, 1, 1, '2013-01-02 00:00:00'),
(2, 1, 1, '2013-01-02 00:00:00'),
(3, 1, 1, '2013-02-02 00:00:00'),
(4, 1, 1, '2013-02-02 00:00:00'),
(5, 1, 1, '2013-02-02 00:00:00'),
(6, 2, 1, '2012-02-02 00:00:00'),
(7, 2, 1, '2012-02-02 00:00:00'),
(8, 2, 1, '2012-01-20 00:00:00'),
(9, 2, 1, '2013-01-02 00:00:00'),
(10, 2, 1, '2013-01-02 00:00:00');

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

--
-- Table structure for table `tblsites`
--

CREATE TABLE IF NOT EXISTS `tblsites` (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`SiteName` varchar(100) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

--
-- Dumping data for table `tblsites`
--

INSERT INTO `tblsites` (`ID`, `SiteName`) VALUES
(1, 'Site 1'),
(2, 'Site 2');

编辑 2:

接受 steves 的建议,我已将查询更改为此

SELECT tblmovements.SiteID, tblsites.SiteName FROM tblmovements
INNER JOIN tblsites
ON tblmovements.SiteID = tblsites.ID
WHERE (tblmovements.TicketStatus = 0 OR tblmovements.TicketStatus = 1)
AND tblmovements.DateRequired>='2013-01-01 00:00:00' AND tblmovements.DateRequired<='2013-01-31 23:59:59'
GROUP BY tblmovements.SiteID

现在处于半工作状态。我现在遇到的问题是,这只是在该日期范围内有票时选择。我现在需要做的只是返回结果集,如果 tblmovements 中的条目是该站点 ID 在该表中的第一次出现。如果返回到主查询,您会注意到子选择上有一个 IF。

编辑 3

是的,我想我已经根据史蒂夫的输入和非星期五早上的白痴突然闪现破解了它。

SELECT tblmovements.SiteID, tblsites.SiteName FROM tblmovements
INNER JOIN tblsites
ON tblmovements.SiteID = tblsites.ID
WHERE (tblmovements.TicketStatus = 0 OR tblmovements.TicketStatus = 1)
AND tblmovements.DateRequired>='2013-01-01 00:00:00' AND tblmovements.DateRequired<='2013-01-31 23:59:59'
AND (SELECT COUNT(*) FROM tblmovements t3 WHERE t3.DateRequired<'2013-01-01 00:00:00' AND t3.SiteID=tblmovements.SiteID)<=0
GROUP BY tblmovements.SiteID

添加了一个额外的条件,只是在开始日期之前给我一个票数,所以理论上如果它返回一个结果集,其中在我要求的日期之间有票并且在开始日期之前没有票,那么所有返回的 siteid 应该是我需要的。

到目前为止的测试正在返回我期望的数据集,这很好,而且它明显更快查询执行时间 0.5711 秒奖励。

最佳答案

加入而不是子查询和 IN 列表怎么样?

SELECT t1.SiteID, t2.* FROM tblmovements t1
WHERE (TicketStatus = 0 OR TicketStatus = 1)
AND t1.DateRequired BETWEEN '2013-01-01 00:00:00' AND '2013-01-31 23:59:59'
GROUP BY t1.SiteID)
INNER JOIN tblsites t2
ON t1.SiteID = t2.ID

编辑 1 - 回复评论:

我在这里所做的是将您的 IF 评估转移到 WHERE 条件语句中。

原始查询会选择大范围的行,然后评估它们以写入它们的 SiteID 或 ''。当您可以使用 where 条件缩小范围时,为什么要选择较大的范围?

关于mysql - 使用子选择和 IF 条件的缓慢 MySQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15022240/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com