我想我失去了它! : - /
所以,我有这个MySQL UPDATE查询...
UPDATE `Jobs`
SET `Archived` = 'Y'
WHERE `JobCode` IN (
SELECT `JobCode` FROM (
SELECT m.`JobCode`
FROM `Jobs` as jx
JOIN (
SELECT j.`JobCode`, MAX(c.`CutDate`) AS MaxCutDate
FROM `Cuts` AS c
LEFT JOIN `Jobs` AS j ON (j.`JobCode`=c.`JobCode`)
GROUP BY j.`JobCode`
) AS m ON (m.`JobCode`=jx.`JobCode`)
WHERE m.MaxCutDate < '2014-01-01'
) AS tmp_table
)
表Customers
,Jobs
和Cuts
是简单关系组的一部分。 Customers
有多个Jobs
,Jobs
有多个Cuts
。 我在这里提出了这个问题的复杂性,因为我不确定它是否是问题的一部分,并且不想过度简化问题。
查询的目的是为所有Jobs
设置Archived
。'Y'
至Jobs
根据{{1}}。Cut
字段,自2014-01-01 OK
之前未创建Cuts
条记录的记录。当时看起来很简单。
所以问题是这个;查询正确的以下部分生成单个列结果,仅包含CutDate
个JobCode
个文件,其中Cut
个记录没有Cut
。CutDate
自2014-01-01
...
这可以按预期工作......
SELECT `JobCode` FROM (
SELECT m.`JobCode`
FROM `Jobs` as jx
JOIN (
SELECT j.`JobCode`, MAX(c.`CutDate`) AS MaxCutDate
FROM `Cuts` AS c
LEFT JOIN `Jobs` AS j ON (j.`JobCode`=c.`JobCode`)
GROUP BY j.`JobCode`
) AS m ON (m.`JobCode`=jx.`JobCode`)
WHERE m.MaxCutDate < '2014-01-01'
) AS tmp_table
[注意:双重SELECT(SELECT ...)))是为了解决MySQL的一个愚蠢但众所周知的问题。我觉得这里没问题。 ]
举个例子,上面可能会产生以下内容......
JobCode
-------
930
935
936
在JobCode
表中也恰好有Jobs
的931到934。这些不包含在上述结果中,因为它们没有Cut
个CutDate
的记录比2014-01-01
更新。这就是我想要的和我期望的。
HOWEVER ...当我运行完整查询时,包括UPDATE
部分......
UPDATE `Jobs`
SET `Archived` = 'Y'
WHERE `JobCode` IN (
SELECT `JobCode` FROM (
SELECT m.`JobCode`
FROM `Jobs` as jx
JOIN (
SELECT j.`JobCode`, MAX(c.`CutDate`) AS MaxCutDate
FROM `Cuts` AS c
LEFT JOIN `Jobs` AS j ON (j.`JobCode`=c.`JobCode`)
GROUP BY j.`JobCode`
) AS m ON (m.`JobCode`=jx.`JobCode`)
WHERE m.MaxCutDate < '2014-01-01'
) AS tmp_table
)
......那么,疯狂的事情似乎发生了!我期望的是Jobs
输出中存在的唯一SELECT
条记录应该更新。但随机的其他Jobs
记录也可以!我说,&#34;随机&#34;,因为a)我找不到他们的押韵或理由。
所以,这就是问题所在。请哦,非常好,非常好 ...我想念WTF吗?
非常感谢!
答案 0 :(得分:1)
我认为左连接的顺序不正确。您希望包含Jobs表中的所有JobCodes,然后如果Cuts表中有记录,那么您希望包含它们(如果存在)。
在此情况下,如果裁员记录不存在,CutDate将为空,您也无法处理会发生的事情。
SELECT j.`JobCode`
FROM `Jobs` as j
LEFT JOIN `Cuts` AS c ON c.`JobCode` = j.`JobCode`
GROUP BY j.`JobCode`
HAVING MAX(IFNULL(c.`CutDate`, '2016-01-01')) < '2014-01-01'
因此,日期可以设置为2014年之后或之前,具体取决于您是否要存档记录,如果不存在记录的Cuts。您可以使用having语句来处理聚合函数,以便使用max函数,然后比较它是否小于2014。
我不确定为什么你会看到随机结果,但我认为左连接不正确并且可能没有在更新语句中对JOBS表进行别名。我建议在运行更新之前先测试一下。
# ju will stand for "Jobs Update"
SELECT ju.`JobCode`
FROM `Jobs` ju
WHERE ju.`JobCode` IN (
SELECT j.`JobCode`
FROM `Jobs` as j
LEFT JOIN `Cuts` AS c ON c.`JobCode` = j.`JobCode`
GROUP BY j.`JobCode`
HAVING MAX(IFNULL(c.`CutDate`, '2016-01-01')) < '2014-01-01'
)
如果您已准备好运行更新,则可以将其切换。
# ju will stand for "Jobs Update"
UPDATE `Jobs` ju
SET ju.`Archived` = 'Y'
WHERE ju.`JobCode` IN (
SELECT j.`JobCode`
FROM `Jobs` as j
LEFT JOIN `Cuts` AS c ON c.`JobCode` = j.`JobCode`
GROUP BY j.`JobCode`
HAVING MAX(IFNULL(c.`CutDate`, '2016-01-01')) < '2014-01-01'
)
答案 1 :(得分:1)
您是否尝试过JOIN
而不是WHERE
条件?
UPDATE `Jobs`
JOIN (SELECT `JobCode` FROM (
SELECT m.`JobCode`
FROM `Jobs` as jx
JOIN (
SELECT j.`JobCode`, MAX(c.`CutDate`) AS MaxCutDate
FROM `Cuts` AS c
JOIN `Jobs` AS j ON (j.`JobCode`=c.`JobCode`)
GROUP BY j.`JobCode`
) AS m ON (m.`JobCode`=jx.`JobCode`)
WHERE m.MaxCutDate < '2014-01-01'
) AS tmp_table
) AS t ON t.`JobCode` = `Jobs`.`JobCode`
SET `Archived` = 'Y'
我还将子查询中的LEFT JOIN
替换为JOIN
。由于我们选择的JobCode
必须存在于表Jobs
中 - 这对于UPDATE
是必要的。如果JobCode
为空,那么根据我的理解,没有任何内容可以更新。
答案 2 :(得分:0)
感谢大家的好建议。你是完全正确的。
最后,“随机”结果实际上是周围PHP代码中的一个错误。随机工作实际上并未存档。
最重要的是,我正在使用phpMyAdmin
,它显然有一个(另一个:-P)错误。当我使用子查询时,它会报告“零(0)行受影响”,当时这不是真的!我相信这一点,并且在查询后没有进一步检查实际的表格内容。我浪费了很多这样的时间。 : - /
在LEFT JOIN中丢失LEFT肯定有助于Job没有相关的Cuts记录。
最后,我选择了@Andrew的版本,因为我认为它是最有效的,因为没有使用HAVING ......那就是我最初尝试的方式,所以感觉更好嘿......
<!-- language: SQL -->
UPDATE `Jobs`
JOIN (SELECT `JobCode` FROM (
SELECT m.`JobCode`
FROM `Jobs` as jx
JOIN (
SELECT j.`JobCode`, MAX(c.`CutDate`) AS MaxCutDate
FROM `Cuts` AS c
JOIN `Jobs` AS j ON (j.`JobCode`=c.`JobCode`)
GROUP BY j.`JobCode`
) AS m ON (m.`JobCode`=jx.`JobCode`)
WHERE m.MaxCutDate < '2014-01-01'
) AS tmp_table
) AS t ON t.`JobCode` = `Jobs`.`JobCode`
SET `Archived` = 'Y'
再次感谢!