0

See this SQL Fiddle. It generates a list with the id-s of all descendants of the element with id 10.

If I add an INDEX on the column ParentId, the result set changes. Now only the children of the root element are included, and not all the descendants. See this SQL Fiddle.

Is this a bug in MySQL? I don't think adding an INDEX should ever change the result set of a query.

If I change the id of the root element, so that it is smaller than the id of the other elements, it works again even with the INDEX. See this SQL Fiddle.

The query, which generates a list with the id-s of all descendants of an element x, works like this:

  1. Concatenate the id-s of all elements whose parent is x.
  2. Concatenate the id-s of all elements whose parent is in the list generated in the previous step.
  3. Repeat step 2 until there are no more elements to add.
  4. Concatenate all the lists into one long list of id-s.

Here is the query, where <id> is the id of the element x:

SELECT GROUP_CONCAT(Level SEPARATOR ',') FROM (
   SELECT @Ids := (
       SELECT GROUP_CONCAT(`Id` SEPARATOR ',')
       FROM `Table`
       WHERE FIND_IN_SET(`ParentId`, @Ids)
   ) Level
   FROM `Table`
   JOIN (SELECT @Ids := <id>) temp1
   WHERE FIND_IN_SET(`ParentId`, @Ids)
) temp2

For completion, here is the database schema that gives an incorrect result set:

CREATE TABLE `Table` (
   `Id` int(8),
   `ParentId` int(8),
   INDEX(`ParentId`)
);

INSERT INTO `Table` (Id, ParentId)
VALUES
   (10, NULL),
   (2, 10),
   (3, 2),
   (4, 2),
   (5, 10);
Magnar Myrtveit
  • 2,432
  • 3
  • 30
  • 51
  • The assumption that an index should not change the resultset only applies if you actually use sets. You are evaluating row based (because of the variables), so the row (or here: execution) order can be relevant (e.g. `limit 10` depends on an order too). But in your case, it's just that your query is wrong. Remove the 2nd `WHERE FIND_IN_SET(ParentId, @Ids)`, and it [should work](http://www.sqlfiddle.com/#!9/006d73/45). On a more general note: there are other ways to [model trees](https://stackoverflow.com/q/4048151/6248528) in a database (especially one that doesn't support CTEs). – Solarflare Nov 22 '17 at 16:06
  • @Solarflare indeed, it looks like it works correctly without second `WHERE`. – Wirone Nov 22 '17 at 16:32
  • @Solarflare Thanks! You are of course right. Amazing that I didn't see that. If you put that in an answer I'd be happy to accept it :) – Magnar Myrtveit Nov 23 '17 at 08:03

0 Answers0