programing

조건을 복제하면 다른 결과 집합이 나타납니다.

javajsp 2023. 11. 5. 11:00

조건을 복제하면 다른 결과 집합이 나타납니다.

다음과 같은 문의 사항이 있습니다.

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
   ))
)

보시다시피 두 조건이 동일하기 때문에 하나의 조건을 제거했다면 쿼리에서도 동일한 결과가 나와야 합니다.그러나 쿼리는 두 조건이 모두 있을 때 둘 중 하나만 사용할 때와는 다른 결과를 반환합니다!

조건에 사용된 내부 쿼리(아래)가 반환됩니다.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에 문제가 있는 것 같습니다.여기 MySQL을 사용한 SQL Fiddle이 있으며, 정확한 결과를 제공합니다.SQL Fiddle에서는 MariaDB를 사용할 수 없을 것 같습니다.MariaDB에서 쿼리를 테스트할 수 있는 다른 쉬운 방법이 있습니까?

MySQL 및 MariaDB의 최신 버전에서 문제가 발생한 것으로 보입니다.

다음 데이터베이스에서 문제가 발생합니다.

  • MySQL 5.7.17
  • MariaDB 10.1.25

그러나 이러한 데이터베이스에서는 잘 작동합니다.

  • MySQL 5.6.35
  • MySQL 5.5.51

데이터베이스에 문제가 있는지 테스트하려면 다음 쿼리를 수행합니다.마지막 쿼리는 4개의 행을 반환해야 합니다.하나의 행만 반환하는 경우 데이터베이스 버전이 문제의 영향을 받습니다.

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 테스트용 피들입니다.MySQL 8.0에서도 이 문제가 발생합니다.

https://www.db-fiddle.com/f/5SAJZJosQXMZsDmU1Lmi8X/0

언급URL : https://stackoverflow.com/questions/40129204/duplicating-the-condition-gives-a-different-result-set