-1

J'ai une table avec des millions d'enregistrements, la relation est un (objet) à plusieurs (objets_objets).en sélectionnant l'élément todo suivant de la table enfant

object_items:

CREATE TABLE `object_items` (
    `item_name` varchar(50) NOT NULL DEFAULT '', 
    `object_id` int(10) unsigned NOT NULL DEFAULT '0', 
    `sequence` int(10) unsigned NOT NULL, 
    `completed` tinyint(1) NOT NULL DEFAULT '0', 
    `is_active` tinyint(1) NOT NULL DEFAULT '0', 
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `uni_seq_object_id` (`sequence`,`object_id`), 
    KEY `idx_object_id` (`object_id`), 
    KEY `idx_seq` (`sequence`) 
) ENGINE=InnoDB AUTO_INCREMENT=3408237 DEFAULT CHARSET=utf8mb4 

données Exemple:

+-----------+-----------+----------+-----------+------+ 
| item_name | object_id | sequence | completed | id | 
+-----------+-----------+----------+-----------+------+ 
| ABCD  |  10 |  1 |   1 | 1 | 
| BCDE  |  10 |  2 |   1 | 2 | 
| CDEF  |  10 |  3 |   1 | 3 | 
| DEFG  |  10 |  4 |   0 | 4 | 
| ABCD  |  11 |  1 |   1 | 5 | 
| BCDE  |  11 |  2 |   1 | 6 | 
| CDEF  |  11 |  3 |   0 | 7 | 
| DEFG  |  11 |  4 |   0 | 8 | 
| ABCD  |  12 |  1 |   1 | 9 | 
| BCDE  |  12 |  2 |   1 | 10 | 
+-----------+-----------+----------+-----------+------+ 

Résultat souhaité:

+-----------+-----------+----------+-----------+------+ 
| item_name | object_id | sequence | completed | id | 
+-----------+-----------+----------+-----------+------+ 
| DEFG  |  10 |  4 |   0 | 4 | 
| CDEF  |  11 |  3 |   0 | 7 | 
+-----------+-----------+----------+-----------+------+ 

La requête que je fonctionne:

select 
    a.* 
from object_items a 
where a.sequence = (
    select min(sequence) 
    from object_items b 
    where a.object_id = b.object_id 
    and b.completed = 0 
) 

Ce qui fonctionne réellement, mais quand je l'utilise limite, mais si je lance count(*) il meurt juste.

Expliquer la requête:

+----+--------------------+-------+------------+------+---------------+---------------+---------+-----------------+---------+----------+-------------+ 
| id | select_type  | table | partitions | type | possible_keys | key   | key_len | ref    | rows | filtered | Extra  | 
+----+--------------------+-------+------------+------+---------------+---------------+---------+-----------------+---------+----------+-------------+ 
| 1 | PRIMARY   | a  | NULL  | ALL | NULL   | NULL   | NULL | NULL   | 3268598 | 100.00 | Using where | 
| 2 | DEPENDENT SUBQUERY | b  | NULL  | ref | idx_object_id | idx_object_id | 4  | db.a.object_id |  21 | 10.00 | Using where | 
+----+--------------------+-------+------------+------+---------------+---------------+---------+-----------------+---------+----------+-------------+ 

Y at-il une meilleure façon d'obtenir l'article suivant TODO qui est pas encore terminée, par séquence, uniquement pour les objets ceux-ci ont au moins un élément à faire, avec base de données lourde comme ça?

Merci

+0

Dup de https://dba.stackexchange.com/questions/180397/selecting-next-todo-item-from-child-table –

Répondre

1
SELECT a.* 
FROM (
    SELECT object_id, MIN(sequence) AS sequence 
    FROM object_items b 
    WHERE b.completed = 0 
    GROUP BY object_id 
) AS m 
INNER JOIN object_items a 
    USING (object_id, sequence) 

Ajouter un index sur les colonnes (completed, object_id, sequence) pour optimiser la sous-requête.

Ajoutez un index sur les colonnes (object_id, sequence) pour optimiser la requête externe.

+0

Cela fonctionne très bien, merci beaucoup. –