复制条件给出不同的结果集
Duplicating the condition gives a different result set
我有以下查询:
SELECT *
FROM dp_organisation_member t82
WHERE (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level + '1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
) AND (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level+'1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
)
如您所见,这两个条件是相同的,所以如果我删除其中一个条件,查询应该会给出相同的结果。但是,查询 returns 当两个条件都存在时与仅使用其中一个条件时的结果不同!
条件中使用的内部查询(以下)returns 115,131,153
在我的例子中。
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level+'1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
同时使用这两个条件时,结果仅包括具有 OrganisationId = 1
的行。当仅使用其中一个条件时,OrganisationId
等于 115
、131
或 153
的行也包括在内。
所以下面的查询产生了正确的结果:
SELECT *
FROM dp_organisation_member t82
WHERE (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level + '1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
)
此外,如果我用该查询的结果替换其中一个内部查询,该查询会给出正确的结果:
SELECT *
FROM dp_organisation_member t82
WHERE (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, "115,131,153")
) AND (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level+'1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
)
这个问题中的第一个查询,具有重复的条件,但是没有给出正确的结果。
谁能解释一下这种行为?
编辑
我认为这可能是 MariaDB 的问题。这是 SQL Fiddle 和 MySQL,给出了正确的结果。在SQLFiddle中似乎无法使用MariaDB。还有其他简单的方法可以在 MariaDB 中测试查询吗?
这似乎是新版本 MySQL 和 MariaDB 的问题。
我在这些数据库中遇到了问题:
- MySQL 5.7.17
- MariaDB 10.1.25
但它在这些数据库中工作正常:
- MySQL 5.6.35
- MySQL 5.5.51
要测试您的数据库是否存在该问题,请执行以下查询。最终查询应该 return 4 行。如果它 return 只有一行,则说明您的数据库版本受到问题的影响。
CREATE TABLE `dp_organisation` (
`OrganisationId` bigint(32) NOT NULL AUTO_INCREMENT,
`ParentId` bigint(32) DEFAULT NULL,
PRIMARY KEY (`OrganisationId`)
) ENGINE=MyISAM AUTO_INCREMENT=154 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `dp_organisation_member` (
`OrganisationId` bigint(32) NOT NULL,
`UserId` bigint(32) NOT NULL,
PRIMARY KEY (`OrganisationId`,`UserId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `dp_organisation` VALUES (1,NULL),(2,NULL),(3,2),(115,1),(131,1),(153,115);
INSERT INTO `dp_organisation_member` VALUES (1,1),(2,2),(3,3),(115,4),(131,5),(153,6);
SELECT *
FROM dp_organisation_member t82
WHERE (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level + '1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
) AND (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level+'1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
)
编辑
错误已由 MySQL 验证:https://bugs.mysql.com/bug.php?id=87339
编辑 2018-10-30
这是一个 fiddle 用于测试它。 MySQL 8.0.
中也存在此问题
我有以下查询:
SELECT *
FROM dp_organisation_member t82
WHERE (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level + '1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
) AND (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level+'1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
)
如您所见,这两个条件是相同的,所以如果我删除其中一个条件,查询应该会给出相同的结果。但是,查询 returns 当两个条件都存在时与仅使用其中一个条件时的结果不同!
条件中使用的内部查询(以下)returns 115,131,153
在我的例子中。
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level+'1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
同时使用这两个条件时,结果仅包括具有 OrganisationId = 1
的行。当仅使用其中一个条件时,OrganisationId
等于 115
、131
或 153
的行也包括在内。
所以下面的查询产生了正确的结果:
SELECT *
FROM dp_organisation_member t82
WHERE (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level + '1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
)
此外,如果我用该查询的结果替换其中一个内部查询,该查询会给出正确的结果:
SELECT *
FROM dp_organisation_member t82
WHERE (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, "115,131,153")
) AND (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level+'1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
)
这个问题中的第一个查询,具有重复的条件,但是没有给出正确的结果。
谁能解释一下这种行为?
编辑
我认为这可能是 MariaDB 的问题。这是 SQL Fiddle 和 MySQL,给出了正确的结果。在SQLFiddle中似乎无法使用MariaDB。还有其他简单的方法可以在 MariaDB 中测试查询吗?
这似乎是新版本 MySQL 和 MariaDB 的问题。
我在这些数据库中遇到了问题:
- MySQL 5.7.17
- MariaDB 10.1.25
但它在这些数据库中工作正常:
- MySQL 5.6.35
- MySQL 5.5.51
要测试您的数据库是否存在该问题,请执行以下查询。最终查询应该 return 4 行。如果它 return 只有一行,则说明您的数据库版本受到问题的影响。
CREATE TABLE `dp_organisation` (
`OrganisationId` bigint(32) NOT NULL AUTO_INCREMENT,
`ParentId` bigint(32) DEFAULT NULL,
PRIMARY KEY (`OrganisationId`)
) ENGINE=MyISAM AUTO_INCREMENT=154 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `dp_organisation_member` (
`OrganisationId` bigint(32) NOT NULL,
`UserId` bigint(32) NOT NULL,
PRIMARY KEY (`OrganisationId`,`UserId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `dp_organisation` VALUES (1,NULL),(2,NULL),(3,2),(115,1),(131,1),(153,115);
INSERT INTO `dp_organisation_member` VALUES (1,1),(2,2),(3,3),(115,4),(131,5),(153,6);
SELECT *
FROM dp_organisation_member t82
WHERE (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level + '1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
) AND (
t82.`OrganisationId` = '1' OR FIND_IN_SET(t82.`OrganisationId`, (
SELECT GROUP_CONCAT(`Ids`)
FROM (
SELECT @Level := @Level+'1' `Level`, @Ids := (
SELECT GROUP_CONCAT(`OrganisationId`)
FROM dp_organisation
WHERE FIND_IN_SET(`ParentId`, @Ids)
) `Ids`
FROM (SELECT @Ids := '1', @Level := '0') temp1
INNER JOIN dp_organisation ON NOT(ISNULL(@Ids))
) temp2
))
)
编辑
错误已由 MySQL 验证:https://bugs.mysql.com/bug.php?id=87339
编辑 2018-10-30 这是一个 fiddle 用于测试它。 MySQL 8.0.
中也存在此问题