Trucs et astuces pour MySQL

10 octobre 2017

Une page où vous pourrez avoir réponse à presque toutes vos questions concernant MySQL!

Publicités

Quick Guide On How To Ask A MySQL-related Question Properly

1 août 2016

Note: this article was originally posted in French here.

You!  Yes!  Yep, you! I’m talking to you my friend!  You, the one that I help out in forums, on IRC, on mailing lists!

Each and every day, I answer questions related to MySQL, mostly about SQL queries or optimization problems. Whether it’s on dBForums, Stack Overflow, MySQL.com, developpez.net or on IRC (irc.freenode.net, channel #mysql), it’s always the same thing! If you want me to help you, make it easy for me!

So, here’s a quick guide explaining what you have to do if you want us/me to help you solve your problem as quickly as possible.

Explain what your problem is as simply and clearly as possible

If you’re unable to explain, in one sentence, what you are trying to do, we’re off to a very bad start.  You have to know what you’re talking about first!  You have to know what you’re trying to do in the first place!

A good example: « I’m trying to find the best salesman in every store located in a district that sells less than the national district average« . This is clear and simple to understand!

A bad example: « My SQL query is slow, there it is » :

SELECT
 COUNT(*) AS x1k1, w.nndt, w.n01_d
FROM 
 p_usr_htgg w
WHERE
 EXISTS (SELECT 
    w2.id
   FROM 
    puw_user w2
   LEFT JOIN 
    temp_eoms te ON te.mt = w2.mt
   WHERE 
    w2.k1 = w.k1 AND w.sales = MAX(w2.sales)
   )
GROUP BY 
 w.nndt, w.n01_d
HAVING 
 COUNT(*) > 3
ORDER BY 
 x1k1 DESC
LIMIT 
 0, 100 

Can you see the difference between these two examples? In one case, the problem is clear.  In the second case, just seeing the SQL without any further explanation makes me want to puke! How can I help with all that SQL garbage?

Start small!  If you have no clue about how to use JOINs, don’t focus on the the ROLLUP or aggregate stuff!!!  Learn the basics while you’re at it! Learn the lingo as well.  If you don’t know what something means, ask it! Don’t pretend you know when you don’t!

One more thing : pick names that are meaningful for tables and columns! Acronyms and cryptic abbreviations tell me nothing! Same thing for table and column names in Italian, Greek, Spanish or German!  Use English !

Be precise

« I have a huge database with an enormous amount of concurrent users and my query is very slow and it is executed many many times« .

What is huge for you is probably a joke for Google, Amazon and GitHub or for someone working in bioinformatics: give me numbers (number of records, tablespace size, etc.), not your impressions!

« Enormous » is often relative! Fifty concurrent users and a table of 100 million rows on a server with 2G of RAM is an enormous amount of users! But on a server with 16 processors and 128G of RAM, 50 concurrent users is not a problem at all : once again, give me numbers, not adjectives!

« Many many times » doesn’t mean anything to me! What does that mean exactly? 200 times/minute? 15 times per minute? What? Give me precise numbers! What do you mean by slow? 3 seconds or 0.2 seconds? Be precise!

Don’t make me google for you

Please, make some minimal effort! Often times, I can give you an URL explaining your problem faster than the time it took you to write your question!  You would have saved everyone’s precious time if you would have googled in the first place!

Give me some test data and expected results

« It doesn’t work!  I should have six xyz records for every abcd record but I only get five ».

This tells me nothing useful!  I don’t know your database, your tables, your domain, the content of the columns, etc.  Even worse, I don’t know what’s in those tables, how the data is spread out, the selectivity of some columns, etc. Creating a test example with some data only takes two minutes on SQLFiddle!

Show me the EXPLAIN

Your query is slow? So what! Why? I have no way to know unless you give me the EXPLAIN of your query, I cannot help you at all nor even know why MySQL picks a particular access plan over a more promising one!

Show me the SHOW CREATE TABLE

Even if you provided me with the EXPLAIN of your SQL query, I still need to know what the table looks like.  One is useless without the other! I also need the SHOW CREATE TABLE, it’s as simple as that!

Are both keys referenced in your JOIN of the same type and length? Is the LIKE in your query way too slow because we have to scan 4Mb of text in every record? Are we trying to match records by looking into a 1G BLOB column?  Is it an InnoDB, a MyISAM or another table type?  What are the character set and collation?

Learn to use SHOW VARIABLES

In some cases, your query is fine and the problems you encounter are caused by session/server/client parameters!  You have to know how to use SHOW VARIABLES!

Learn to use SHOW STATUS

Sometimes, you have to be able to check the status of your server. This is essential! In that case, SHOW STATUS is another command you must know!

Use SHOW TABLE STATUS

The SHOW TABLE STATUS will allow you, in a glance, to have a precise picture of what’s in your database.  You’ll be able to see, in one shot, table names, their type, their size, collation info, etc. Very useful command : for you and for me!

Give me some volumetrics

I just said it earlier and I’ll say it again : I need numbers, measures, to help you! Give me numbers, not fuzzy impressions!

Most of your queries execute in 0.1 second but your server cannot keep up? Why? Perhaps, it would have been useful to know that you have 3500 concurrent connections at any moment hitting this poor server!  Or that one particular query is executed 900 times per minute!

Your query takes 27 seconds to complete? Perhaps you should have told me that your table has 728 million records!

You wonder why the EXPLAIN of your query shows a full table scan even though you’ve indexed just about everything on that table? Had I known your table only has 8 records, I would have told you that in that case a full table scan is perfectly normal!

If you want me to help you, I need a minimum of context !  Only numbers can tell me the real story!  Not « enormous » nor « many » or « slow » !

Take a deep breath : do not panic!

Premature optimization is the root of all evil.

« I have this HYPER-HUGE-BIGGEST-OH-MY-GOD database and my query, with 2 INNER JOIN, is executed every 15 seconds and we add 2500 records to the main table every month… »

Take it easy!  Relax!  MySQL is not Excel : it can handle lots of data! For my own amusement, my server at home has 10000+ tables! Performance is mostly a matter of hardware and every database is different!

Unless you’re trying to compete with Google or you have a very complex query that causes real problems, don’t try to optimize every SQL query and make it execute in less that 100 milliseconds! In some cases, it’s just not possible possible.  Focus on the real problems!

Don’t make me sweat over a query for 4 hours and end up telling me that this SQL runs once a year on January 1st at 2h15 AM and it takes 5 minutes to complete when only 2 users are connected!  Pick your battles! I don’t mind helping you out but I don’t like to waste my time!

Don’t try to optimize everything!  Work on what counts!

Use SQLFiddle

It’s easy to use and it works great when debugging SQL queries!  And it’s free!  And it’s here!  And it allows us to work on exactly the same thing!

Use a pastebin

Please, don’t flood the IRC channel with a query of 35 lines!  It’s annoying for everyone and it’s rude! Use a pastebin (or even better, SQLFiddle). There’s Pastie, gist.github et pastebin.com.

Use the MySQL client

Some problems are extremely hard to reproduce and difficult to understand. The last thing we need is some PHP code on top of your query!  Another thing: please, don’t use crap like PHPMyAdmin or any other clumsy tool when trying to debug or fix things! All you need is the MySQL client !  It works just fine on every platform supported by MySQL, it’s rock solid and, honestly, it’s all you need! If you’re on Windows, you can always use HeidiSQL.

Use \G

Instead of forcing me to scroll to the right for eons just to see the complete result of your query, an EXPLAIN or a SHOW TABLE STATUS, add \G at the end of your SQL statement to force the client to display results vertically and limit them to 80 chars per line if necessary!

Format your code

SELECT count(*) as
x1k1, w.nndt, 
w.n01_d
from P_USR_HTGG 
w where exists (
SELECT w2.id FROM puw_user w2
left join 
temp_eoms te ON te.mt = w2.mt where 
w2.k1 = w.k1 AND w.sales = 
MAX(w2.sales))
group by w.nndt,
w.n01_d
having count(*) > 3
order BY x1k1 
desc limit 0, 100

Can you quickly see what going on in that query? Not me! And it’s the exact same query that was at the beginning of this post!  Which one is easier to read?

Write the reserved words and functions in uppercase! SELECT, FROM, WHERE, INNER JOIN, SUBSTRING, HAVING, GROUP BY, ORDER BY, IN, EXISTS, COUNT, etc. Indent your code and regroup « logical » parts (for instance, sub-selects) of the work done by your query. If I have to read your query with a magnifier to identify what I’m looking for, it doesn’t help!

Don’t be overexcited

We’ve been working on your query for 30 minutes and now you’re satisfied with the speed and results?  Comes out you only needed an extra index?

Don’t precipitate yourself to add the index in production! What sometimes takes 3 seconds on test data can take hours on a production database! Besides, when applying changes to a production database, you should always make sure you have a recent backup first!

This advice can sound somewhat useless and stupid but not so long ago, a poor guy I was helping had the very bright idea to add the missing index to his production database right away… only to realize that his production table had 94 million records!  The index creation took a few hours… during the peak hours!

Be open to criticism

Lots of times, a poor design or a bad choice of data types is the problem, not the circumvoluted query you’re trying to optimize.  Your query is unnecessary complex because of this! Be open to suggestions : we’re just trying to help you!

Like here.

Say thanks

I’m helping people with their MySQL/SQL problems because I like it and the diverse nature of problems out there helps me stay mentally sharp and up-to-date with MySQL.  If I spend 2 hours of my time helping you, a « thank you » is not much to ask in return!

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save

Save


Guide rapide de la question MySQL bien posée

15 mars 2016

Oui!  Toi mon ami!  Oui!  Toi!  C’est à toi que je m’adresse!  Celui que je dépanne et que j’aide « gratis » à chaque jour!

Je réponds quotidiennement à des questions au sujet de MySQL, principalement de requêtes et d’optimisation.  Que ce soit sur dBForums, Stack Overflow, MySQL.com, developpez.net ou sur IRC (irc.freenode.net, channel #mysql), c’est toujours la même chose.  Si tu veux que je t’aide, aide-moi à t’aider!

Donc, un petit guide de ce qu’il faut faire pour qu’on puisse résoudre ton problème le plus rapidement possible.

Explique ton problème clairement

Si tu es incapable d’expliquer, en une phrase, ce que tu tentes de faire, ça part mal!  Encore faudrait-il que tu saches ce que tu veux et ce dont tu parles!

Par exemple : « je cherche le meilleur vendeur pour chaque magasin se trouvant dans un district qui vend moins que la moyenne nationale« . Ça, c’est clair et limpide!

Cependant, « ma requête est lente, la voici » :

SELECT 
 COUNT(*) AS x1k1, w.nndt, w.n01_d
FROM 
 p_usr_htgg w
WHERE
 EXISTS (SELECT 
    w2.id
   FROM 
    puw_user w2
   LEFT JOIN 
    temp_eoms te ON te.mt = w2.mt
   WHERE 
    w2.k1 = w.k1 AND w.sales = MAX(w2.sales)
   )
GROUP BY 
 w.nndt, w.n01_d
HAVING 
 COUNT(*) > 3
ORDER BY 
 x1k1 DESC
LIMIT 
 0, 100

Tu vois la différence? Dans un des 2 cas le problème est clair! Dans le second cas, juste à voir la requête je n’ai pas le goût de t’aider!

Et utilise des noms de tables et de colonnes que je puisse comprendre! Les acronymes et abbréviations cryptiques ne m’aident pas!  Pas plus que si tes noms de tables ou de colonnes sont en italien, en espagnol ou en allemand!

Sois précis

« J’ai une base de données gigantesque avec énormément d’usagers concurrents et ma requête est très lente et elle est effectuée très souvent« .

Ce qui est « gigantesque » pour toi est probablement ridicule pour Google, Amazon et GitHub ou quelqu’un qui oeuvre dans le domaine de la bio-informatique : donne-moi des chiffres!

« Énormément« , c’est bien souvent relatif!  50 usagers concurrents et une table de 100 millions d’enregistrements sur une machine avec 2G de RAM, c’est effectivement énorme!  Mais avec un serveur 16 processeurs et 128G de RAM, c’est minuscule : donne-moi des chiffres!

« Souvent », c’est quoi pour toi? 200 fois par minute? 15 fois par minute? Quoi? Donne-moi des chiffres!

Qu’est-ce que la lenteur pour toi? 3 secondes ou 0.2 secondes? Donne-moi des chiffres!

Ne me fais pas googler à ta place

Fais un minimum d’effort!  Il me faut souvent moins de temps pour trouver un lien qui te réfère à la solution que tu en as pris à écrire la question!  Tu te serais sauvé du temps si tu avais googlé à ma place! Et moi aussi j’en aurais sauvé!

Quelques données et les résultats attendus

« Oui mais je devrais avoir 6 records de xyz pour ce abcd et j’en ai seulement 5 ».

Cela ne me dit strictement rien!  Je ne connais pas ta base de donnée, ou ton domaine, pas plus que tes tables ou les colonnes de tes tables.  Encore moins tes données, leur type, leur répartition, leur sélectivité, etc…

Un exemple de table, de données et ta requête, ça se fait en 2 minutes sur SQLFiddle!

Fournis-moi le EXPLAIN

Ta requête est lente…  So what!  Pour quelles raisons?  Je ne le sais pas plus que toi!  Si tu ne me fournis pas le EXPLAIN, je suis incapable de t’aider, encore moins de savoir pourquoi MySQL choisit un plan d’accès aussi moche!

Montre-moi le SHOW CREATE TABLE

Même si j’ai le EXPLAIN, il me faut la SHOW CREATE TABLE, c’est aussi simple que ça!  L’un ne va pas sans l’autre!

Est-ce que dans ta jointure les 2 clés sont du même type et de la même longueur?  Est-ce que le LIKE est lent parce qu’on scanne une colonne de texte de 4Mb ou que t’as un BLOB de 1G qui contient un vidéo dans chaque enregistrement?  Est-ce que ta table est de type InnoDb, MyISAM ou autre?

Apprend à utiliser SHOW VARIABLES

Dans certains cas, ton problème n’est pas ta requête SQL mais certains paramètres de ta session, ton serveur, etc.  Tu dois savoir utiliser SHOW VARIABLES!

Apprend à utiliser SHOW STATUS

Tu dois savoir être en mesure de vérifier l’état de ton serveur.  C’est primordial ! SHOW STATUS est un autre de tes amis précieux!

Apprend à utiliser SHOW TABLE STATUS

SHOW TABLE STATUS te permettra, en un rapide coup d’oeil, d’avoir un aperçu des tables de ta base de donnée : leur type, le nombre de records, la taille moyenne des records, etc.

Donne-moi des données volumétriques

Te l’ai-je dit plus haut?  Donne-moi des chiffres!

Tes requêtes s’exécutent quasiment toutes en 0.1 seconde mais ton serveur est essoufflé?  Pourquoi? Peut-être que je devrais savoir que tu as 3500 usagers concurrents qui vargent sur le même serveur! Ou que ta requête est exécutée 900 fois par minute!

Ta requête prend 27 secondes? Je devrais peut-être savoir que cette table a 728 millions d’enregistrements!

Tu te demandes pourquoi le EXPLAIN montre un table scan même si tu as tous les indexes au monde sur cette table? Peut-être que MySQL a choisi de faire un full table scan parce que ta table de jointure a seulement 8 enregistrements!

Un minimum de contexte m’aide à comprendre ce qui se passe!

Respire : ne capote pas!

« J’ai une HYPER GROSSE base de données, avec une requête qui a 2 jointures qui roule aux 15 secondes.  J’ajoute à la table principale 2500 records par mois… »

Tu n’es pas dans Excel!  Respire!  Pour mon amusement personnel, j’ai un serveur avec plus de 10000 tables à la maison.  Tout est question de hardware et de perspective et chaque base de donnée a ses particularités.

À moins que ton intention soit de compétionner Google ou qu’une requête soit *vraiment* problématique, n’essaie pas de faire en sorte que chaque requête roule en moins de 100 millisecondes!

Ne me fais pas suer à t’aider pendant 4 heures sur une requête de rapport annuel qui prend 5 minutes un 1er janvier à 2h15 de la nuit et qui roule une fois par année! Choisis tes combats!  J’veux bien t’aider mais pas perdre mon temps!

Arrête de vouloir tout optimiser aveuglément!

Utilise SQLFiddle

C’est facile, utile et pratique.  Et c’est gratuit! Et c’est ici. Et ça nous permet de travailler sur exactement la même chose!

Utilise un pastebin

S’il te plait, n’inonde pas le channel IRC avec une requête de 35 lignes! Utilise SQLFiddle ou un pastebin. Y’a Pastie, gist.github et pastebin.com.

Utilise le client MySQL

Certains problèmes sont extrêmement subtils et difficiles à comprendre et à isoler.  La dernière chose dont j’ai besoin, c’est du code PHP, une application client merdique comme PHPMyAdmin ou un autre outil boiteux.  Le client MySQL fonctionne à merveille et c’est parfait et tout ce dont tu as besoin.  Au pire, utilise des outils solides comme HeidiSQL mais pas PHPMyAdmin s’il te plait!

Et où que tu sois, sur toutes les plates-formes, le client MySQL est là! Un seul outil à apprendre et à maîtriser!

Utilise \G

Au lieu de me forcer à scroller vers la droite pendant une éternité pour que je puisse voir les résultats d’une requête, d’un EXPLAIN ou d’un SHOW TABLE STATUS, ajoute \G à la fin!

Ça limite l’affichage à 80 caractères et les données sont disposées de façon verticale.  C’est beaucoup plus lisible quand les résultats dépassent 80 caractères par ligne!

Mais en toute circonstance, va au plus simple.  Si le résultat est affichable sans \G, ça me va!  Si j’ai à scroller vers la droite parce que je ne peux pas voir la ligne entière, utilise \G!

Formatte ton code

SELECT count(*) as
x1k1, w.nndt, 
w.n01_d
from P_USR_HTGG 
w where exists (
SELECT w2.id FROM puw_user w2
left join 
temp_eoms te ON te.mt = w2.mt where 
w2.k1 = w.k1 AND w.sales = 
MAX(w2.sales))
group by w.nndt,
w.n01_d
having count(*) > 3
order BY x1k1 
desc limit 0, 100

Tu vois clairement tout ce qui se passe dans cette requête? Pas moi! Et c’est exactement la même requête que celle présentée plus haut! Laquelle des deux trouves-tu la plus lisible?

Applique-toi à mettre les mots réservés en majuscules! Regarde comment les parties d’une requête sont regroupées et indentées. S’il faut scruter ta requête à la loupe pour identifier la clause WHERE, le EXISTS, le COUNT, le GROUP BY et les autres indices nécessaires à la compréhension de ta requête, ça ne facilite la tâche à personne!

Ne sois pas trop fébrile

Y’a déjà 30 minutes qu’on travaille ensemble sur ta requête et tu es satisfait du résultat, ton problème est enfin résolu? Il ne te manquait qu’un index?

Ne te précipite pas pour ajouter l’index manquant en production! Ce qui a pris 3 secondes sur tes données de test peut prendre des heures en production!  Par ailleurs, vérifies que tu as un backup avant de toucher à la prod!

Ça semble idiot comme conseil mais pas plus tard que la semaine passé, un type que j’ai aidé, pris d’un enthousiasme démesuré, a eu la bonne idée d’immédiatement créer l’index qui lui manquait en production… en oubliant le fait qu’il avait 94 millions d’enregistrements dans cette table!

La création de l’index a pris quelques heures… en plein aux heures de pointe du serveur!  Outch!

Sois ouvert à la critique

Dans bien des cas, le mauvais design des tables ou la façon de représenter tes données est 95% de ton problème. Sois ouvert aux suggestions : je n’essaie que de t’aider!

Comme ici.

Dis merci

J’aide les gens parce que ça me fait plaisir et que la diversité des problèmes rencontrés m’aide à rester sharp et up-to-date avec MySQL.  Si je passe 2 heures à t’aider et à te donner de mon temps, un merci c’est bien peu cher payé et très apprécié!

 

 

 


Bio-informatique

20 juillet 2013

Je vous parlais, en début d’année, de BioSmalltalk (une librairie d’outils pour la bio-informatique écrite en Smalltalk disponible sur Pharo et Squeak).

Sachez que les auteurs (Hernán F. Morales et Guillermo Giovambattista) publieront un article (en anglais) dans le Bioinformatics Journal (de la prestigieuse Université d’Oxford).  Le sysnopsis de cet article est disponible ici.

Sur la même thématique, il se passe de belles choses à l’Université de Montréal en génomique et en épidémiologie au laboratoire de recherche Philip Awadalla pour le projet CARTaGENE.  Vous trouverez ici un article expliquant quels ont été les motifs qui ont poussé le laboratoire de recherche à utiliser MySQL et à préférer le moteur de stockage TokuDB à MyISAM quand est venu le temps de traiter des milliards de mutations dans leur base de données de façon performante.

 


Comment presser un citron (troisième partie)

27 mai 2013

1. Un problème n’arrive jamais seul

Dans la deuxième partie de cet article (le premier article étant ici), nous nous sommes laissés sur un exemple extrême (i.e. une grille avec des lignes et des colonnes vides) afin de vérifier la validité et l’efficacité de la solution présentée dans un des pires scénarios envisageable :

Avant même de débuter, rappelez-vous qu’il est primordial d’exécuter la commande suivante dans votre session pour éviter d’avoir à attendre une éternité, que ce soit pour la requête SQL ou pour un EXPLAIN!

set @@optimizer_search_depth = 3;

Qu’arriverait-il si nous avions à solutionner un sudoku contenant à la fois des lignes et des colonnes vides, comme dans l’exemple ci-haut avec la requête suivante:

SELECT *
FROM sudoku_combined_view
WHERE
(r2c2 = 3) AND (r2c3 = 4) AND (r2c4 = 8) AND (r2c5 = 2) AND
(r2c6 = 5) AND (r2c7 = 6) AND (r2c8 = 9) AND (r3c2 = 5) AND
(r3c3 = 9) AND (r3c4 = 3) AND (r3c5 = 6) AND (r3c6 = 4) AND
(r3c7 = 1) AND (r3c8 = 8) AND (r4c2 = 9) AND (r4c3 = 7) AND
(r4c4 = 1) AND (r4c5 = 8) AND (r4c6 = 2) AND (r4c7 = 5) AND
(r4c8 = 6) AND (r6c2 = 8) AND (r6c3 = 1) AND (r6c4 = 4) AND
(r6c5 = 7) AND (r6c6 = 6) AND (r6c7 = 2) AND (r6c8 = 3) AND
(r7c2 = 2) AND (r7c3 = 5) AND (r7c4 = 6) AND (r7c5 = 4) AND
(r7c6 = 1) AND (r7c7 = 9) AND (r7c8 = 7) AND (r8c2 = 7) AND
(r8c3 = 6) AND (r8c4 = 5) AND (r8c5 = 3) AND (r8c6 = 8) AND
(r8c7 = 4) AND (r8c8 = 2);

Examinons le résultat du EXPLAIN pour la grille en question:

+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+-------------------------------+------+----------------------------------------------------------+
| id | select_type | table | type        | possible_keys                                                                                                                                      | key         | key_len | ref                           | rows | Extra                                                    |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+-------------------------------+------+----------------------------------------------------------+
|  1 | SIMPLE      | col3  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i38,i48 | 2,2,2   | NULL                          |   64 | Using intersect(i23,i38,i48); Using where                |
|  1 | SIMPLE      | r2    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i58     | 2,2     | NULL                          |   68 | Using intersect(i23,i58); Using where; Using join buffer |
|  1 | SIMPLE      | r3    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i78,i56     | 2,2     | NULL                          |   68 | Using intersect(i78,i56); Using where; Using join buffer |
|  1 | SIMPLE      | r4    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i38,i46     | 2,2     | NULL                          |   68 | Using intersect(i38,i46); Using where; Using join buffer |
|  1 | SIMPLE      | r6    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i67     | 2,2     | NULL                          |   68 | Using intersect(i23,i67); Using where; Using join buffer |
|  1 | SIMPLE      | r7    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i38,i56     | 2,2     | NULL                          |   68 | Using intersect(i38,i56); Using where; Using join buffer |
|  1 | SIMPLE      | r8    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i68     | 2,2     | NULL                          |   68 | Using intersect(i23,i68); Using where; Using join buffer |
|  1 | SIMPLE      | col2  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i68     | 2,2     | NULL                          |   68 | Using intersect(i23,i68); Using where; Using join buffer |
|  1 | SIMPLE      | col4  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i78,i46     | 2,2     | NULL                          |   68 | Using intersect(i78,i46); Using where; Using join buffer |
|  1 | SIMPLE      | col5  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i68     | 2,2     | NULL                          |   68 | Using intersect(i23,i68); Using where; Using join buffer |
|  1 | SIMPLE      | col6  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i67     | 2,2     | NULL                          |   68 | Using intersect(i23,i67); Using where; Using join buffer |
|  1 | SIMPLE      | col7  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i68     | 2,2     | NULL                          |   68 | Using intersect(i23,i68); Using where; Using join buffer |
|  1 | SIMPLE      | col8  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i37,i24     | 2,2     | NULL                          |   68 | Using intersect(i37,i24); Using where; Using join buffer |
|  1 | SIMPLE      | col1  | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23         | 2       | sudoku.r2.c1,sudoku.r3.c1     | 5040 | Using where                                              |
|  1 | SIMPLE      | r1    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12         | 2       | sudoku.col1.c1,sudoku.col2.c1 | 5040 | Using where                                              |
|  1 | SIMPLE      | r5    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12         | 2       | sudoku.col1.c5,sudoku.col2.c5 | 5040 | Using where                                              |
|  1 | SIMPLE      | r9    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12         | 2       | sudoku.col1.c9,sudoku.col2.c9 | 5040 | Using where                                              |
|  1 | SIMPLE      | col9  | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12         | 2       | sudoku.r1.c9,sudoku.r2.c9     | 5040 | Using where                                              |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+-------------------------------+------+----------------------------------------------------------+
18 rows in set (0.20 sec)

À première vue, tout semble correct! Aucun table scan et les indexes sont utilisés pour chaque colonne et chaque rangée non vide!

Et en combien de temps MySQL peut-il « solutionner » cette grille ?

Fantastique!  1.5 seconde!  Tout est réglé!  Malheureusement, non…

2. Le pire scénario possible

Il existe une catégorie de sudokus que nombre de mathématiciens et d’informaticiens étudient depuis des années : ces grilles minimales n’ont seulement que 17 révélés, le minimum théorique (une conjecture encore non prouvée de façon mathématique par Gary McGuire, Bastian Tugemann et Gilles Civario, un autre intéressant article ici) pouvant mener à une solution unique.  Plusieurs de ces grilles spéciales (17 révélés) sont depuis des années compilées par Gordon Royle, professeur à l’université d’Australie Occidentale.

Comme celle-ci :

Vous remarquerez que cette grille ne contient aucune ligne ni aucune colonne vide! Essayons donc de voir en combien de temps MySQL pourra résoudre celle-ci :

mysql> SELECT *
 -> FROM sudoku_combined_view
 -> WHERE
 -> (r1c8 = 1) AND
 -> (r2c1 = 4) AND
 -> (r3c2 = 2) AND
 -> (r4c5 = 5) AND
 -> (r4c7 = 4) AND
 -> (r4c9 = 7) AND
 -> (r5c3 = 8) AND
 -> (r5c7 = 3) AND
 -> (r6c3 = 1) AND
 -> (r6c5 = 9) AND
 -> (r7c1 = 3) AND
 -> (r7c4 = 4) AND
 -> (r7c7 = 2) AND
 -> (r8c2 = 5) AND
 -> (r8c4 = 1) AND
 -> (r9c4 = 8) AND
 -> (r9c6 = 6);
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| r1c1 | r1c2 | r1c3 | r1c4 | r1c5 | r1c6 | r1c7 | r1c8 | r1c9 | r2c1 | r2c2 | r2c3 | r2c4 | r2c5 | r2c6 | r2c7 | r2c8 | r2c9 | r3c1 | r3c2 | r3c3 | r3c4 | r3c5 | r3c6 | r3c7 | r3c8 | r3c9 | r4c1 | r4c2 | r4c3 | r4c4 | r4c5 | r4c6 | r4c7 | r4c8 | r4c9 | r5c1 | r5c2 | r5c3 | r5c4 | r5c5 | r5c6 | r5c7 | r5c8 | r5c9 | r6c1 | r6c2 | r6c3 | r6c4 | r6c5 | r6c6 | r6c7 | r6c8 | r6c9 | r7c1 | r7c2 | r7c3 | r7c4 | r7c5 | r7c6 | r7c7 | r7c8 | r7c9 | r8c1 | r8c2 | r8c3 | r8c4 | r8c5 | r8c6 | r8c7 | r8c8 | r8c9 | r9c1 | r9c2 | r9c3 | r9c4 | r9c5 | r9c6 | r9c7 | r9c8 | r9c9 |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
|   6  |   9  |   3  |   7  |   8  |   4  |   5  |   1  |   2  |   4  |   8  |   7  |   5  |   1  |   2  |   9  |   3  |   6  |   1  |   2  |   5  |   9  |   6  |   3  |   8  |   7  |   4  |   9  |   3  |   2  |   6  |   5  |   1  |   4  |   8  |   7  |   5  |   6  |   8  |   2  |   4  |   7  |   3  |   9  |   1  |   7  |   4  |   1  |   3  |   9  |   8  |   6  |   2  |   5  |   3  |   1  |   9  |   4  |   7  |   5  |   2  |   6  |   8  |   8  |   5  |   6  |   1  |   2  |   9  |   7  |   4  |   3  |   2  |   7  |   4  |   8  |   3  |   6  |   1  |   5  |   9  |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
1 row in set (2 min 20.83 sec)

Ouch!  Je ne suis pas arrivé à descendre sour la barre des 40 secondes malgré mes tentatives répétées et ce, sur différents serveurs avec différentes configurations (et même différentes autres grilles de 17 révélés). Les résultats pour solutionner cette grille vont de près de 40 secondes à plus de 33 minutes. Le résultat du EXPLAIN parle par lui-même :

+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+---------+---------+-------------------------------+------+----------------------------------------------------------+
| id | select_type | table | type        | possible_keys                                                                                                                                      | key     | key_len | ref                           | rows | Extra                                                    |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+---------+---------+-------------------------------+------+----------------------------------------------------------+
|  1 | SIMPLE      | r4    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i57,i59 | 2,2     | NULL                          |  624 | Using intersect(i57,i59); Using where                    |
|  1 | SIMPLE      | r7    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i14,i47 | 2,2     | NULL                          |  624 | Using intersect(i14,i47); Using where; Using join buffer |
|  1 | SIMPLE      | col4  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i78,i89 | 2,2     | NULL                          |  624 | Using intersect(i78,i89); Using where; Using join buffer |
|  1 | SIMPLE      | col7  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i45,i47 | 2,2     | NULL                          |  624 | Using intersect(i45,i47); Using where; Using join buffer |
|  1 | SIMPLE      | r8    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i24     | 2       | const,const                   | 5000 | Using where                                              |
|  1 | SIMPLE      | r9    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i46     | 2       | const,const                   | 5001 | Using where                                              |
|  1 | SIMPLE      | col1  | range       | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i27     | 2       | NULL                          | 5000 | Using where; Using join buffer                           |
|  1 | SIMPLE      | r5    | range       | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i37     | 2       | NULL                          | 5001 | Using where; Using join buffer                           |
|  1 | SIMPLE      | r6    | range       | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i35     | 2       | NULL                          | 5001 | Using where; Using join buffer                           |
|  1 | SIMPLE      | col3  | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i45     | 2       | sudoku.r4.c3,const            | 5040 | Using where                                              |
|  1 | SIMPLE      | col2  | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i34     | 2       | const,sudoku.r4.c2            | 5040 | Using where                                              |
|  1 | SIMPLE      | r2    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12     | 2       | const,sudoku.col2.c2          | 5040 | Using where                                              |
|  1 | SIMPLE      | col5  | range       | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i46     | 2       | NULL                          | 5001 | Using where; Using join buffer                           |
|  1 | SIMPLE      | r3    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12     | 2       | sudoku.col1.c3,const          | 5040 | Using where                                              |
|  1 | SIMPLE      | col8  | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12     | 2       | const,sudoku.r2.c8            | 5040 | Using where                                              |
|  1 | SIMPLE      | r1    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12     | 2       | sudoku.col1.c1,sudoku.col2.c1 | 5040 | Using where                                              |
|  1 | SIMPLE      | col9  | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12     | 2       | sudoku.r1.c9,sudoku.r2.c9     | 5040 | Using where                                              |
|  1 | SIMPLE      | col6  | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12     | 2       | sudoku.r1.c6,sudoku.r2.c6     | 5040 | Using where                                              |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+---------+---------+-------------------------------+------+----------------------------------------------------------+
18 rows in set (2.59 sec)

Observez la colonne rows dans le résultat du EXPLAIN pour comprendre le nombre astronomique de jointures possibles que MySQL aura à effectuer et à tester…  Dans la très grande majorité des cas, ce chiffre est supérieur à 5000!

Il devient maintenant évident que notre solution ne tient plus la route…

3. Ne pas céder au découragement!

Il existe bon nombre d’autres possibilités d’optimisations que nous n’avons toujours pas envisagées.  Par exemple, dans certains cas il pourrait être avantageux de chercher par boîtes (carré de 3×3 dans le sudoku).  Certaines grilles de 17 révélés pourraient grandement en bénéficier mais il nous faudrait alors joindre 27 tables!  Ce qui est gagné d’un côté est perdu de l’autre.

Nous pourrions également créer des partitions mais dans ce cas, quelles seraient les chances qu’une colonne ou une rangée contienne la donnée permettant de discriminer et de choisir la partition requise?

Nous pourrions augmenter la taille de l’index pour passer de 2 colones à 3 mais l’impact de cette mesure serait inutile pour les grilles de 17 révélés.

Qu’arriverait-il si nous passions du format de table MyISAM à InnoDb ?  Absolument rien, le problème demeure entier : MySQL n’est pas assez rapide pour lire les données (ou les indexes) sur disque puis les joindre efficacement dans un cas aussi extrême.

L’idée à la base de cette série d’article était d’arriver à solutionner un sudoku valide en n’utilisant que du SQL.  Un sudoku valide, par définition, a une seule solution.  Nous aurions pu ajouter LIMIT 1 à chacune de nos vues mais hélas, ce faisant, nos vues seraient contraintes d’utiliser l’algorithme TEMPTABLE au lieu de MERGE, ce qui serait catastrophique!

Évidemment, quelques autres astuces existent, comme augmenter la taille des variables key_buffer_size et join_buffer_size, diminuer la valeur du optimizer_search_depth, etc.  Évidemment dans le cas des 2 premières variables, je ne peux rien vous suggérer comme ces paramètres dépendent de la mémoire RAM disponible sur votre machine, le système d’exploitation utilisé, etc.  Quant à la valeur de la variable optimizer_search_depth, diminuer celle-ci n’aura pas d’impact significatif comme le problème réside dans la lenteur des accès au disque dur et au nombre effarant de jointures et de rangées à examnier (et à retrouver puis lire).

4. Éplucher toutes les options

Il existe un type de table, MEMORY, en MySQL qui nous permettrait d’éviter d’avoir à lire les données (ou les indexes) sur disque, ce qui pourrait avoir un impact majeur dans notre cas.  Nous allons donc créer cette table en mémoire et la remplir tout en créant les indexes nécessaires (exactement les mêmes vues et indexes que la table de format MyISAM).

Mais avant de procéder, prenez bien soin de vous assurez que la variable max_heap_table_size soit supérieure à 216Mb ( 226492416) sinon vous vous heurterez à une tonne d’erreurs 1114 (table full).  Si ce n’est pas le cas, vous pouvez fixer la valeur de cette variable à 216Mb comme suit :

set @@max_heap_table_size =  226492416;

Une fois cette précaution prise, construisez la table et les indexes nécessaires comme suit:

USE sudoku;

DROP TABLE IF EXISTS positions_memory;
CREATE TABLE positions_memory (
 c1 TINYINT UNSIGNED NOT NULL,
 c2 TINYINT UNSIGNED NOT NULL,
 c3 TINYINT UNSIGNED NOT NULL,
 c4 TINYINT UNSIGNED NOT NULL,
 c5 TINYINT UNSIGNED NOT NULL,
 c6 TINYINT UNSIGNED NOT NULL,
 c7 TINYINT UNSIGNED NOT NULL,
 c8 TINYINT UNSIGNED NOT NULL,
 c9 TINYINT UNSIGNED NOT NULL
) ENGINE=MEMORY;

INSERT INTO positions_memory (c1, c2, c3, c4, c5, c6, c7, c8, c9)
SELECT c1, c2, c3, c4, c5, c6, c7, c8, c9 FROM positions;

CREATE INDEX i12 ON positions_memory(c1, c2) USING HASH; CREATE INDEX i13 ON positions_memory(c1, c3) USING HASH;
CREATE INDEX i14 ON positions_memory(c1, c4) USING HASH; CREATE INDEX i15 ON positions_memory(c1, c5) USING HASH;
CREATE INDEX i16 ON positions_memory(c1, c6) USING HASH; CREATE INDEX i17 ON positions_memory(c1, c7) USING HASH;
CREATE INDEX i18 ON positions_memory(c1, c8) USING HASH; CREATE INDEX i19 ON positions_memory(c1, c9) USING HASH;
CREATE INDEX i23 ON positions_memory(c2, c3) USING HASH; CREATE INDEX i24 ON positions_memory(c2, c4) USING HASH;
CREATE INDEX i25 ON positions_memory(c2, c5) USING HASH; CREATE INDEX i26 ON positions_memory(c2, c6) USING HASH;
CREATE INDEX i27 ON positions_memory(c2, c7) USING HASH; CREATE INDEX i28 ON positions_memory(c2, c8) USING HASH;
CREATE INDEX i29 ON positions_memory(c2, c9) USING HASH; CREATE INDEX i34 ON positions_memory(c3, c4) USING HASH;
CREATE INDEX i35 ON positions_memory(c3, c5) USING HASH; CREATE INDEX i36 ON positions_memory(c3, c6) USING HASH;
CREATE INDEX i37 ON positions_memory(c3, c7) USING HASH; CREATE INDEX i38 ON positions_memory(c3, c8) USING HASH;
CREATE INDEX i39 ON positions_memory(c3, c9) USING HASH; CREATE INDEX i45 ON positions_memory(c4, c5) USING HASH;
CREATE INDEX i46 ON positions_memory(c4, c6) USING HASH; CREATE INDEX i47 ON positions_memory(c4, c7) USING HASH;
CREATE INDEX i48 ON positions_memory(c4, c8) USING HASH; CREATE INDEX i49 ON positions_memory(c4, c9) USING HASH;
CREATE INDEX i56 ON positions_memory(c5, c6) USING HASH; CREATE INDEX i57 ON positions_memory(c5, c7) USING HASH;
CREATE INDEX i58 ON positions_memory(c5, c8) USING HASH; CREATE INDEX i59 ON positions_memory(c5, c9) USING HASH;
CREATE INDEX i67 ON positions_memory(c6, c7) USING HASH; CREATE INDEX i68 ON positions_memory(c6, c8) USING HASH;
CREATE INDEX i69 ON positions_memory(c6, c9) USING HASH; CREATE INDEX i78 ON positions_memory(c7, c8) USING HASH;
CREATE INDEX i79 ON positions_memory(c7, c9) USING HASH; CREATE INDEX i89 ON positions_memory(c8, c9) USING HASH;
CREATE INDEX i9 ON positions_memory(c9) USING HASH;

Maintenant, il s’agit de recréer les trois mêmes vues que nous avons créées pour le type de table MYISAM mais pour notre nouvelle table.

En premier lieu, la vue sur les rangées.

USE sudoku;

DROP VIEW IF EXISTS sudoku_memory_rows_view;
CREATE VIEW sudoku_memory_rows_view AS
SELECT
r1.c1 as r1c1, r1.c2 as r1c2, r1.c3 as r1c3, r1.c4 as r1c4, r1.c5 as r1c5, r1.c6 as r1c6, r1.c7 as r1c7, r1.c8 as r1c8, r1.c9 as r1c9, r2.c1 as r2c1,
r2.c2 as r2c2, r2.c3 as r2c3, r2.c4 as r2c4, r2.c5 as r2c5, r2.c6 as r2c6, r2.c7 as r2c7, r2.c8 as r2c8, r2.c9 as r2c9, r3.c1 as r3c1, r3.c2 as r3c2,
r3.c3 as r3c3, r3.c4 as r3c4, r3.c5 as r3c5, r3.c6 as r3c6, r3.c7 as r3c7, r3.c8 as r3c8, r3.c9 as r3c9, r4.c1 as r4c1, r4.c2 as r4c2, r4.c3 as r4c3,
r4.c4 as r4c4, r4.c5 as r4c5, r4.c6 as r4c6, r4.c7 as r4c7, r4.c8 as r4c8, r4.c9 as r4c9, r5.c1 as r5c1, r5.c2 as r5c2, r5.c3 as r5c3, r5.c4 as r5c4,
r5.c5 as r5c5, r5.c6 as r5c6, r5.c7 as r5c7, r5.c8 as r5c8, r5.c9 as r5c9, r6.c1 as r6c1, r6.c2 as r6c2, r6.c3 as r6c3, r6.c4 as r6c4, r6.c5 as r6c5,
r6.c6 as r6c6, r6.c7 as r6c7, r6.c8 as r6c8, r6.c9 as r6c9, r7.c1 as r7c1, r7.c2 as r7c2, r7.c3 as r7c3, r7.c4 as r7c4, r7.c5 as r7c5, r7.c6 as r7c6,
r7.c7 as r7c7, r7.c8 as r7c8, r7.c9 as r7c9, r8.c1 as r8c1, r8.c2 as r8c2, r8.c3 as r8c3, r8.c4 as r8c4, r8.c5 as r8c5, r8.c6 as r8c6, r8.c7 as r8c7,
r8.c8 as r8c8, r8.c9 as r8c9, r9.c1 as r9c1, r9.c2 as r9c2, r9.c3 as r9c3, r9.c4 as r9c4, r9.c5 as r9c5, r9.c6 as r9c6, r9.c7 as r9c7, r9.c8 as r9c8,
r9.c9 as r9c9

FROM
positions_memory r1, positions_memory r2, positions_memory r3,
positions_memory r4, positions_memory r5, positions_memory r6,
positions_memory r7, positions_memory r8, positions_memory r9

WHERE
-- Nombres uniques dans chaque colonne
(r1.c1 <> r2.c1) AND (r1.c1 <> r3.c1) AND (r1.c1 <> r4.c1) AND (r1.c1 <> r5.c1) AND (r1.c1 <> r6.c1) AND (r1.c1 <> r7.c1) AND (r1.c1 <> r8.c1) AND (r1.c1 <> r9.c1) AND (r1.c2 <> r2.c2) AND (r1.c2 <> r3.c2) AND (r1.c2 <> r4.c2) AND (r1.c2 <> r5.c2) AND (r1.c2 <> r6.c2) AND (r1.c2 <> r7.c2) AND (r1.c2 <> r8.c2) AND (r1.c2 <> r9.c2) AND
(r1.c3 <> r2.c3) AND (r1.c3 <> r3.c3) AND (r1.c3 <> r4.c3) AND (r1.c3 <> r5.c3) AND (r1.c3 <> r6.c3) AND (r1.c3 <> r7.c3) AND (r1.c3 <> r8.c3) AND (r1.c3 <> r9.c3) AND (r1.c4 <> r2.c4) AND (r1.c4 <> r3.c4) AND (r1.c4 <> r4.c4) AND (r1.c4 <> r5.c4) AND (r1.c4 <> r6.c4) AND (r1.c4 <> r7.c4) AND (r1.c4 <> r8.c4) AND (r1.c4 <> r9.c4) AND
(r1.c5 <> r2.c5) AND (r1.c5 <> r3.c5) AND (r1.c5 <> r4.c5) AND (r1.c5 <> r5.c5) AND (r1.c5 <> r6.c5) AND (r1.c5 <> r7.c5) AND (r1.c5 <> r8.c5) AND (r1.c5 <> r9.c5) AND (r1.c6 <> r2.c6) AND (r1.c6 <> r3.c6) AND (r1.c6 <> r4.c6) AND (r1.c6 <> r5.c6) AND (r1.c6 <> r6.c6) AND (r1.c6 <> r7.c6) AND (r1.c6 <> r8.c6) AND (r1.c6 <> r9.c6) AND
(r1.c7 <> r2.c7) AND (r1.c7 <> r3.c7) AND (r1.c7 <> r4.c7) AND (r1.c7 <> r5.c7) AND (r1.c7 <> r6.c7) AND (r1.c7 <> r7.c7) AND (r1.c7 <> r8.c7) AND (r1.c7 <> r9.c7) AND (r1.c8 <> r2.c8) AND (r1.c8 <> r3.c8) AND (r1.c8 <> r4.c8) AND (r1.c8 <> r5.c8) AND (r1.c8 <> r6.c8) AND (r1.c8 <> r7.c8) AND (r1.c8 <> r8.c8) AND (r1.c8 <> r9.c8) AND
(r1.c9 <> r2.c9) AND (r1.c9 <> r3.c9) AND (r1.c9 <> r4.c9) AND (r1.c9 <> r5.c9) AND (r1.c9 <> r6.c9) AND (r1.c9 <> r7.c9) AND (r1.c9 <> r8.c9) AND (r1.c9 <> r9.c9) AND (r2.c1 <> r3.c1) AND (r2.c1 <> r4.c1) AND (r2.c1 <> r5.c1) AND (r2.c1 <> r6.c1) AND (r2.c1 <> r7.c1) AND (r2.c1 <> r8.c1) AND (r2.c1 <> r9.c1) AND (r2.c2 <> r3.c2) AND
(r2.c2 <> r4.c2) AND (r2.c2 <> r5.c2) AND (r2.c2 <> r6.c2) AND (r2.c2 <> r7.c2) AND (r2.c2 <> r8.c2) AND (r2.c2 <> r9.c2) AND (r2.c3 <> r3.c3) AND (r2.c3 <> r4.c3) AND (r2.c3 <> r5.c3) AND (r2.c3 <> r6.c3) AND (r2.c3 <> r7.c3) AND (r2.c3 <> r8.c3) AND (r2.c3 <> r9.c3) AND (r2.c4 <> r3.c4) AND (r2.c4 <> r4.c4) AND (r2.c4 <> r5.c4) AND
(r2.c4 <> r6.c4) AND (r2.c4 <> r7.c4) AND (r2.c4 <> r8.c4) AND (r2.c4 <> r9.c4) AND (r2.c5 <> r3.c5) AND (r2.c5 <> r4.c5) AND (r2.c5 <> r5.c5) AND (r2.c5 <> r6.c5) AND (r2.c5 <> r7.c5) AND (r2.c5 <> r8.c5) AND (r2.c5 <> r9.c5) AND (r2.c6 <> r3.c6) AND (r2.c6 <> r4.c6) AND (r2.c6 <> r5.c6) AND (r2.c6 <> r6.c6) AND (r2.c6 <> r7.c6) AND
(r2.c6 <> r8.c6) AND (r2.c6 <> r9.c6) AND (r2.c7 <> r3.c7) AND (r2.c7 <> r4.c7) AND (r2.c7 <> r5.c7) AND (r2.c7 <> r6.c7) AND (r2.c7 <> r7.c7) AND (r2.c7 <> r8.c7) AND (r2.c7 <> r9.c7) AND (r2.c8 <> r3.c8) AND (r2.c8 <> r4.c8) AND (r2.c8 <> r5.c8) AND (r2.c8 <> r6.c8) AND (r2.c8 <> r7.c8) AND (r2.c8 <> r8.c8) AND (r2.c8 <> r9.c8) AND
(r2.c9 <> r3.c9) AND (r2.c9 <> r4.c9) AND (r2.c9 <> r5.c9) AND (r2.c9 <> r6.c9) AND (r2.c9 <> r7.c9) AND (r2.c9 <> r8.c9) AND (r2.c9 <> r9.c9) AND (r3.c1 <> r4.c1) AND (r3.c1 <> r5.c1) AND (r3.c1 <> r6.c1) AND (r3.c1 <> r7.c1) AND (r3.c1 <> r8.c1) AND (r3.c1 <> r9.c1) AND (r3.c2 <> r4.c2) AND (r3.c2 <> r5.c2) AND (r3.c2 <> r6.c2) AND
(r3.c2 <> r7.c2) AND (r3.c2 <> r8.c2) AND (r3.c2 <> r9.c2) AND (r3.c3 <> r4.c3) AND (r3.c3 <> r5.c3) AND (r3.c3 <> r6.c3) AND (r3.c3 <> r7.c3) AND (r3.c3 <> r8.c3) AND (r3.c3 <> r9.c3) AND (r3.c4 <> r4.c4) AND (r3.c4 <> r5.c4) AND (r3.c4 <> r6.c4) AND (r3.c4 <> r7.c4) AND (r3.c4 <> r8.c4) AND (r3.c4 <> r9.c4) AND (r3.c5 <> r4.c5) AND
(r3.c5 <> r5.c5) AND (r3.c5 <> r6.c5) AND (r3.c5 <> r7.c5) AND (r3.c5 <> r8.c5) AND (r3.c5 <> r9.c5) AND (r3.c6 <> r4.c6) AND (r3.c6 <> r5.c6) AND (r3.c6 <> r6.c6) AND (r3.c6 <> r7.c6) AND (r3.c6 <> r8.c6) AND (r3.c6 <> r9.c6) AND (r3.c7 <> r4.c7) AND (r3.c7 <> r5.c7) AND (r3.c7 <> r6.c7) AND (r3.c7 <> r7.c7) AND (r3.c7 <> r8.c7) AND
(r3.c7 <> r9.c7) AND (r3.c8 <> r4.c8) AND (r3.c8 <> r5.c8) AND (r3.c8 <> r6.c8) AND (r3.c8 <> r7.c8) AND (r3.c8 <> r8.c8) AND (r3.c8 <> r9.c8) AND (r3.c9 <> r4.c9) AND (r3.c9 <> r5.c9) AND (r3.c9 <> r6.c9) AND (r3.c9 <> r7.c9) AND (r3.c9 <> r8.c9) AND (r3.c9 <> r9.c9) AND (r4.c1 <> r5.c1) AND (r4.c1 <> r6.c1) AND (r4.c1 <> r7.c1) AND
(r4.c1 <> r8.c1) AND (r4.c1 <> r9.c1) AND (r4.c2 <> r5.c2) AND (r4.c2 <> r6.c2) AND (r4.c2 <> r7.c2) AND (r4.c2 <> r8.c2) AND (r4.c2 <> r9.c2) AND (r4.c3 <> r5.c3) AND (r4.c3 <> r6.c3) AND (r4.c3 <> r7.c3) AND (r4.c3 <> r8.c3) AND (r4.c3 <> r9.c3) AND (r4.c4 <> r5.c4) AND (r4.c4 <> r6.c4) AND (r4.c4 <> r7.c4) AND (r4.c4 <> r8.c4) AND
(r4.c4 <> r9.c4) AND (r4.c5 <> r5.c5) AND (r4.c5 <> r6.c5) AND (r4.c5 <> r7.c5) AND (r4.c5 <> r8.c5) AND (r4.c5 <> r9.c5) AND (r4.c6 <> r5.c6) AND (r4.c6 <> r6.c6) AND (r4.c6 <> r7.c6) AND (r4.c6 <> r8.c6) AND (r4.c6 <> r9.c6) AND (r4.c7 <> r5.c7) AND (r4.c7 <> r6.c7) AND (r4.c7 <> r7.c7) AND (r4.c7 <> r8.c7) AND (r4.c7 <> r9.c7) AND
(r4.c8 <> r5.c8) AND (r4.c8 <> r6.c8) AND (r4.c8 <> r7.c8) AND (r4.c8 <> r8.c8) AND (r4.c8 <> r9.c8) AND (r4.c9 <> r5.c9) AND (r4.c9 <> r6.c9) AND (r4.c9 <> r7.c9) AND (r4.c9 <> r8.c9) AND (r4.c9 <> r9.c9) AND (r5.c1 <> r6.c1) AND (r5.c1 <> r7.c1) AND (r5.c1 <> r8.c1) AND (r5.c1 <> r9.c1) AND (r5.c2 <> r6.c2) AND (r5.c2 <> r7.c2) AND
(r5.c2 <> r8.c2) AND (r5.c2 <> r9.c2) AND (r5.c3 <> r6.c3) AND (r5.c3 <> r7.c3) AND (r5.c3 <> r8.c3) AND (r5.c3 <> r9.c3) AND (r5.c4 <> r6.c4) AND (r5.c4 <> r7.c4) AND (r5.c4 <> r8.c4) AND (r5.c4 <> r9.c4) AND (r5.c5 <> r6.c5) AND (r5.c5 <> r7.c5) AND (r5.c5 <> r8.c5) AND (r5.c5 <> r9.c5) AND (r5.c6 <> r6.c6) AND (r5.c6 <> r7.c6) AND
(r5.c6 <> r8.c6) AND (r5.c6 <> r9.c6) AND (r5.c7 <> r6.c7) AND (r5.c7 <> r7.c7) AND (r5.c7 <> r8.c7) AND (r5.c7 <> r9.c7) AND (r5.c8 <> r6.c8) AND (r5.c8 <> r7.c8) AND (r5.c8 <> r8.c8) AND (r5.c8 <> r9.c8) AND (r5.c9 <> r6.c9) AND (r5.c9 <> r7.c9) AND (r5.c9 <> r8.c9) AND (r5.c9 <> r9.c9) AND (r6.c1 <> r7.c1) AND (r6.c1 <> r8.c1) AND
(r6.c1 <> r9.c1) AND (r6.c2 <> r7.c2) AND (r6.c2 <> r8.c2) AND (r6.c2 <> r9.c2) AND (r6.c3 <> r7.c3) AND (r6.c3 <> r8.c3) AND (r6.c3 <> r9.c3) AND (r6.c4 <> r7.c4) AND (r6.c4 <> r8.c4) AND (r6.c4 <> r9.c4) AND (r6.c5 <> r7.c5) AND (r6.c5 <> r8.c5) AND (r6.c5 <> r9.c5) AND (r6.c6 <> r7.c6) AND (r6.c6 <> r8.c6) AND (r6.c6 <> r9.c6) AND
(r6.c7 <> r7.c7) AND (r6.c7 <> r8.c7) AND (r6.c7 <> r9.c7) AND (r6.c8 <> r7.c8) AND (r6.c8 <> r8.c8) AND (r6.c8 <> r9.c8) AND (r6.c9 <> r7.c9) AND (r6.c9 <> r8.c9) AND (r6.c9 <> r9.c9) AND (r7.c1 <> r8.c1) AND (r7.c1 <> r9.c1) AND (r7.c2 <> r8.c2) AND (r7.c2 <> r9.c2) AND (r7.c3 <> r8.c3) AND (r7.c3 <> r9.c3) AND (r7.c4 <> r8.c4) AND
(r7.c4 <> r9.c4) AND (r7.c5 <> r8.c5) AND (r7.c5 <> r9.c5) AND (r7.c6 <> r8.c6) AND (r7.c6 <> r9.c6) AND (r7.c7 <> r8.c7) AND (r7.c7 <> r9.c7) AND (r7.c8 <> r8.c8) AND (r7.c8 <> r9.c8) AND (r7.c9 <> r8.c9) AND (r7.c9 <> r9.c9) AND (r8.c1 <> r9.c1) AND (r8.c2 <> r9.c2) AND (r8.c3 <> r9.c3) AND (r8.c4 <> r9.c4) AND (r8.c5 <> r9.c5) AND
(r8.c6 <> r9.c6) AND (r8.c7 <> r9.c7) AND (r8.c8 <> r9.c8) AND (r8.c9 <> r9.c9) AND
-- Nombres uniques dans chaque maison de 3x3
(r1.c1 <> r2.c2) AND (r1.c1 <> r2.c3) AND (r1.c1 <> r3.c2) AND (r1.c1 <> r3.c3) AND (r1.c2 <> r2.c1) AND (r1.c2 <> r2.c3) AND (r1.c2 <> r3.c1) AND (r1.c2 <> r3.c3) AND (r1.c3 <> r2.c1) AND (r1.c3 <> r2.c2) AND (r1.c3 <> r3.c1) AND (r1.c3 <> r3.c2) AND (r1.c4 <> r2.c5) AND (r1.c4 <> r2.c6) AND (r1.c4 <> r3.c5) AND (r1.c4 <> r3.c6) AND
(r1.c5 <> r2.c4) AND (r1.c5 <> r2.c6) AND (r1.c5 <> r3.c4) AND (r1.c5 <> r3.c6) AND (r1.c6 <> r2.c4) AND (r1.c6 <> r2.c5) AND (r1.c6 <> r3.c4) AND (r1.c6 <> r3.c5) AND (r1.c7 <> r2.c8) AND (r1.c7 <> r2.c9) AND (r1.c7 <> r3.c8) AND (r1.c7 <> r3.c9) AND (r1.c8 <> r2.c7) AND (r1.c8 <> r2.c9) AND (r1.c8 <> r3.c7) AND (r1.c8 <> r3.c9) AND
(r1.c9 <> r2.c7) AND (r1.c9 <> r2.c8) AND (r1.c9 <> r3.c7) AND (r1.c9 <> r3.c8) AND (r2.c1 <> r3.c2) AND (r2.c1 <> r3.c3) AND (r2.c2 <> r3.c1) AND (r2.c2 <> r3.c3) AND (r2.c3 <> r3.c1) AND (r2.c3 <> r3.c2) AND (r2.c4 <> r3.c5) AND (r2.c4 <> r3.c6) AND (r2.c5 <> r3.c4) AND (r2.c5 <> r3.c6) AND (r2.c6 <> r3.c4) AND (r2.c6 <> r3.c5) AND
(r2.c7 <> r3.c8) AND (r2.c7 <> r3.c9) AND (r2.c8 <> r3.c7) AND (r2.c8 <> r3.c9) AND (r2.c9 <> r3.c7) AND (r2.c9 <> r3.c8) AND (r4.c1 <> r5.c2) AND (r4.c1 <> r5.c3) AND (r4.c1 <> r6.c2) AND (r4.c1 <> r6.c3) AND (r4.c2 <> r5.c1) AND (r4.c2 <> r5.c3) AND (r4.c2 <> r6.c1) AND (r4.c2 <> r6.c3) AND (r4.c3 <> r5.c1) AND (r4.c3 <> r5.c2) AND
(r4.c3 <> r6.c1) AND (r4.c3 <> r6.c2) AND (r4.c4 <> r5.c5) AND (r4.c4 <> r5.c6) AND (r4.c4 <> r6.c5) AND (r4.c4 <> r6.c6) AND (r4.c5 <> r5.c4) AND (r4.c5 <> r5.c6) AND (r4.c5 <> r6.c4) AND (r4.c5 <> r6.c6) AND (r4.c6 <> r5.c4) AND (r4.c6 <> r5.c5) AND (r4.c6 <> r6.c4) AND (r4.c6 <> r6.c5) AND (r4.c7 <> r5.c8) AND (r4.c7 <> r5.c9) AND
(r4.c7 <> r6.c8) AND (r4.c7 <> r6.c9) AND (r4.c8 <> r5.c7) AND (r4.c8 <> r5.c9) AND (r4.c8 <> r6.c7) AND (r4.c8 <> r6.c9) AND (r4.c9 <> r5.c7) AND (r4.c9 <> r5.c8) AND (r4.c9 <> r6.c7) AND (r4.c9 <> r6.c8) AND (r5.c1 <> r6.c2) AND (r5.c1 <> r6.c3) AND (r5.c2 <> r6.c1) AND (r5.c2 <> r6.c3) AND (r5.c3 <> r6.c1) AND (r5.c3 <> r6.c2) AND
(r5.c4 <> r6.c5) AND (r5.c4 <> r6.c6) AND (r5.c5 <> r6.c4) AND (r5.c5 <> r6.c6) AND (r5.c6 <> r6.c4) AND (r5.c6 <> r6.c5) AND (r5.c7 <> r6.c8) AND (r5.c7 <> r6.c9) AND (r5.c8 <> r6.c7) AND (r5.c8 <> r6.c9) AND (r5.c9 <> r6.c7) AND (r5.c9 <> r6.c8) AND (r7.c1 <> r8.c2) AND (r7.c1 <> r8.c3) AND (r7.c1 <> r9.c2) AND (r7.c1 <> r9.c3) AND
(r7.c2 <> r8.c1) AND (r7.c2 <> r8.c3) AND (r7.c2 <> r9.c1) AND (r7.c2 <> r9.c3) AND (r7.c3 <> r8.c1) AND (r7.c3 <> r8.c2) AND (r7.c3 <> r9.c1) AND (r7.c3 <> r9.c2) AND (r7.c4 <> r8.c5) AND (r7.c4 <> r8.c6) AND (r7.c4 <> r9.c5) AND (r7.c4 <> r9.c6) AND (r7.c5 <> r8.c4) AND (r7.c5 <> r8.c6) AND (r7.c5 <> r9.c4) AND (r7.c5 <> r9.c6) AND
(r7.c6 <> r8.c4) AND (r7.c6 <> r8.c5) AND (r7.c6 <> r9.c4) AND (r7.c6 <> r9.c5) AND (r7.c7 <> r8.c8) AND (r7.c7 <> r8.c9) AND (r7.c7 <> r9.c8) AND (r7.c7 <> r9.c9) AND (r7.c8 <> r8.c7) AND (r7.c8 <> r8.c9) AND (r7.c8 <> r9.c7) AND (r7.c8 <> r9.c9) AND (r7.c9 <> r8.c7) AND (r7.c9 <> r8.c8) AND (r7.c9 <> r9.c7) AND (r7.c9 <> r9.c8) AND
(r8.c1 <> r9.c2) AND (r8.c1 <> r9.c3) AND (r8.c2 <> r9.c1) AND (r8.c2 <> r9.c3) AND (r8.c3 <> r9.c1) AND (r8.c3 <> r9.c2) AND (r8.c4 <> r9.c5) AND (r8.c4 <> r9.c6) AND (r8.c5 <> r9.c4) AND (r8.c5 <> r9.c6) AND (r8.c6 <> r9.c4) AND (r8.c6 <> r9.c5) AND (r8.c7 <> r9.c8) AND (r8.c7 <> r9.c9) AND (r8.c8 <> r9.c7) AND (r8.c8 <> r9.c9) AND
(r8.c9 <> r9.c7) AND (r8.c9 <> r9.c8);

En second lieu, la vue sur les colonnes.

USE sudoku;

DROP VIEW IF EXISTS sudoku_memory_columns_view;
CREATE VIEW sudoku_memory_columns_view AS
SELECT
col1.c1 as r1c1, col1.c2 as r2c1, col1.c3 as r3c1, col1.c4 as r4c1, col1.c5 as r5c1,col1.c6 as r6c1, col1.c7 as r7c1, col1.c8 as r8c1, col1.c9 as r9c1, col2.c1 as r1c2,
col2.c2 as r2c2, col2.c3 as r3c2, col2.c4 as r4c2, col2.c5 as r5c2, col2.c6 as r6c2,col2.c7 as r7c2, col2.c8 as r8c2, col2.c9 as r9c2, col3.c1 as r1c3, col3.c2 as r2c3,
col3.c3 as r3c3, col3.c4 as r4c3, col3.c5 as r5c3, col3.c6 as r6c3, col3.c7 as r7c3,col3.c8 as r8c3, col3.c9 as r9c3, col4.c1 as r1c4, col4.c2 as r2c4, col4.c3 as r3c4,
col4.c4 as r4c4, col4.c5 as r5c4, col4.c6 as r6c4, col4.c7 as r7c4, col4.c8 as r8c4,col4.c9 as r9c4, col5.c1 as r1c5, col5.c2 as r2c5, col5.c3 as r3c5, col5.c4 as r4c5,
col5.c5 as r5c5, col5.c6 as r6c5, col5.c7 as r7c5, col5.c8 as r8c5, col5.c9 as r9c5,col6.c1 as r1c6, col6.c2 as r2c6, col6.c3 as r3c6, col6.c4 as r4c6, col6.c5 as r5c6,
col6.c6 as r6c6, col6.c7 as r7c6, col6.c8 as r8c6, col6.c9 as r9c6, col7.c1 as r1c7,col7.c2 as r2c7, col7.c3 as r3c7, col7.c4 as r4c7, col7.c5 as r5c7, col7.c6 as r6c7,
col7.c7 as r7c7, col7.c8 as r8c7, col7.c9 as r9c7, col8.c1 as r1c8, col8.c2 as r2c8,col8.c3 as r3c8, col8.c4 as r4c8, col8.c5 as r5c8, col8.c6 as r6c8, col8.c7 as r7c8,
col8.c8 as r8c8, col8.c9 as r9c8, col9.c1 as r1c9, col9.c2 as r2c9, col9.c3 as r3c9,col9.c4 as r4c9, col9.c5 as r5c9, col9.c6 as r6c9, col9.c7 as r7c9, col9.c8 as r8c9,
col9.c9 as r9c9
FROM
positions_memory col1, positions_memory col2, positions_memory col3, positions_memory col4,
positions_memory col5, positions_memory col6, positions_memory col7, positions_memory col8, positions_memory col9
WHERE
-- Nombres uniques dans chaque rangee
(col1.c1 <> col2.c1) AND (col1.c1 <> col3.c1) AND (col1.c1 <> col4.c1) AND (col1.c1 <> col5.c1) AND (col1.c1 <> col6.c1) AND (col1.c1 <> col7.c1) AND (col1.c1 <> col8.c1) AND (col1.c1 <> col9.c1) AND (col1.c2 <> col2.c2) AND (col1.c2 <> col3.c2) AND (col1.c2 <> col4.c2) AND (col1.c2 <> col5.c2) AND (col1.c2 <> col6.c2) AND (col1.c2 <> col7.c2) AND (col1.c2 <> col8.c2) AND (col1.c2 <> col9.c2) AND (col1.c3 <> col2.c3) AND (col1.c3 <> col3.c3) AND (col1.c3 <> col4.c3) AND (col1.c3 <> col5.c3) AND (col1.c3 <> col6.c3) AND (col1.c3 <> col7.c3) AND (col1.c3 <> col8.c3) AND (col1.c3 <> col9.c3) AND (col1.c4 <> col2.c4) AND (col1.c4 <> col3.c4) AND (col1.c4 <> col4.c4) AND (col1.c4 <> col5.c4) AND (col1.c4 <> col6.c4) AND (col1.c4 <> col7.c4) AND (col1.c4 <> col8.c4) AND (col1.c4 <> col9.c4) AND
(col1.c5 <> col2.c5) AND (col1.c5 <> col3.c5) AND (col1.c5 <> col4.c5) AND (col1.c5 <> col5.c5) AND (col1.c5 <> col6.c5) AND (col1.c5 <> col7.c5) AND (col1.c5 <> col8.c5) AND (col1.c5 <> col9.c5) AND (col1.c6 <> col2.c6) AND (col1.c6 <> col3.c6) AND (col1.c6 <> col4.c6) AND (col1.c6 <> col5.c6) AND (col1.c6 <> col6.c6) AND (col1.c6 <> col7.c6) AND (col1.c6 <> col8.c6) AND (col1.c6 <> col9.c6) AND (col1.c7 <> col2.c7) AND (col1.c7 <> col3.c7) AND (col1.c7 <> col4.c7) AND (col1.c7 <> col5.c7) AND (col1.c7 <> col6.c7) AND (col1.c7 <> col7.c7) AND (col1.c7 <> col8.c7) AND (col1.c7 <> col9.c7) AND (col1.c8 <> col2.c8) AND (col1.c8 <> col3.c8) AND (col1.c8 <> col4.c8) AND (col1.c8 <> col5.c8) AND (col1.c8 <> col6.c8) AND (col1.c8 <> col7.c8) AND (col1.c8 <> col8.c8) AND (col1.c8 <> col9.c8) AND
(col1.c9 <> col2.c9) AND (col1.c9 <> col3.c9) AND (col1.c9 <> col4.c9) AND (col1.c9 <> col5.c9) AND (col1.c9 <> col6.c9) AND (col1.c9 <> col7.c9) AND (col1.c9 <> col8.c9) AND (col1.c9 <> col9.c9) AND (col2.c1 <> col3.c1) AND (col2.c1 <> col4.c1) AND (col2.c1 <> col5.c1) AND (col2.c1 <> col6.c1) AND (col2.c1 <> col7.c1) AND (col2.c1 <> col8.c1) AND (col2.c1 <> col9.c1) AND (col2.c2 <> col3.c2) AND (col2.c2 <> col4.c2) AND (col2.c2 <> col5.c2) AND (col2.c2 <> col6.c2) AND (col2.c2 <> col7.c2) AND (col2.c2 <> col8.c2) AND (col2.c2 <> col9.c2) AND (col2.c3 <> col3.c3) AND (col2.c3 <> col4.c3) AND (col2.c3 <> col5.c3) AND (col2.c3 <> col6.c3) AND (col2.c3 <> col7.c3) AND (col2.c3 <> col8.c3) AND (col2.c3 <> col9.c3) AND (col2.c4 <> col3.c4) AND (col2.c4 <> col4.c4) AND (col2.c4 <> col5.c4) AND
(col2.c4 <> col6.c4) AND (col2.c4 <> col7.c4) AND (col2.c4 <> col8.c4) AND (col2.c4 <> col9.c4) AND (col2.c5 <> col3.c5) AND (col2.c5 <> col4.c5) AND (col2.c5 <> col5.c5) AND (col2.c5 <> col6.c5) AND (col2.c5 <> col7.c5) AND (col2.c5 <> col8.c5) AND (col2.c5 <> col9.c5) AND (col2.c6 <> col3.c6) AND (col2.c6 <> col4.c6) AND (col2.c6 <> col5.c6) AND (col2.c6 <> col6.c6) AND (col2.c6 <> col7.c6) AND (col2.c6 <> col8.c6) AND (col2.c6 <> col9.c6) AND (col2.c7 <> col3.c7) AND (col2.c7 <> col4.c7) AND (col2.c7 <> col5.c7) AND (col2.c7 <> col6.c7) AND (col2.c7 <> col7.c7) AND (col2.c7 <> col8.c7) AND (col2.c7 <> col9.c7) AND (col2.c8 <> col3.c8) AND (col2.c8 <> col4.c8) AND (col2.c8 <> col5.c8) AND (col2.c8 <> col6.c8) AND (col2.c8 <> col7.c8) AND (col2.c8 <> col8.c8) AND (col2.c8 <> col9.c8) AND
(col2.c9 <> col3.c9) AND (col2.c9 <> col4.c9) AND (col2.c9 <> col5.c9) AND (col2.c9 <> col6.c9) AND (col2.c9 <> col7.c9) AND (col2.c9 <> col8.c9) AND (col2.c9 <> col9.c9) AND (col3.c1 <> col4.c1) AND (col3.c1 <> col5.c1) AND (col3.c1 <> col6.c1) AND (col3.c1 <> col7.c1) AND (col3.c1 <> col8.c1) AND (col3.c1 <> col9.c1) AND (col3.c2 <> col4.c2) AND (col3.c2 <> col5.c2) AND (col3.c2 <> col6.c2) AND (col3.c2 <> col7.c2) AND (col3.c2 <> col8.c2) AND (col3.c2 <> col9.c2) AND (col3.c3 <> col4.c3) AND (col3.c3 <> col5.c3) AND (col3.c3 <> col6.c3) AND (col3.c3 <> col7.c3) AND (col3.c3 <> col8.c3) AND (col3.c3 <> col9.c3) AND (col3.c4 <> col4.c4) AND (col3.c4 <> col5.c4) AND (col3.c4 <> col6.c4) AND (col3.c4 <> col7.c4) AND (col3.c4 <> col8.c4) AND (col3.c4 <> col9.c4) AND (col3.c5 <> col4.c5) AND
(col3.c5 <> col5.c5) AND (col3.c5 <> col6.c5) AND (col3.c5 <> col7.c5) AND (col3.c5 <> col8.c5) AND (col3.c5 <> col9.c5) AND (col3.c6 <> col4.c6) AND (col3.c6 <> col5.c6) AND (col3.c6 <> col6.c6) AND (col3.c6 <> col7.c6) AND (col3.c6 <> col8.c6) AND (col3.c6 <> col9.c6) AND (col3.c7 <> col4.c7) AND (col3.c7 <> col5.c7) AND (col3.c7 <> col6.c7) AND (col3.c7 <> col7.c7) AND (col3.c7 <> col8.c7) AND (col3.c7 <> col9.c7) AND (col3.c8 <> col4.c8) AND (col3.c8 <> col5.c8) AND (col3.c8 <> col6.c8) AND (col3.c8 <> col7.c8) AND (col3.c8 <> col8.c8) AND (col3.c8 <> col9.c8) AND (col3.c9 <> col4.c9) AND (col3.c9 <> col5.c9) AND (col3.c9 <> col6.c9) AND (col3.c9 <> col7.c9) AND (col3.c9 <> col8.c9) AND (col3.c9 <> col9.c9) AND (col4.c1 <> col5.c1) AND (col4.c1 <> col6.c1) AND (col4.c1 <> col7.c1) AND
(col4.c1 <> col8.c1) AND (col4.c1 <> col9.c1) AND (col4.c2 <> col5.c2) AND (col4.c2 <> col6.c2) AND (col4.c2 <> col7.c2) AND (col4.c2 <> col8.c2) AND (col4.c2 <> col9.c2) AND (col4.c3 <> col5.c3) AND (col4.c3 <> col6.c3) AND (col4.c3 <> col7.c3) AND (col4.c3 <> col8.c3) AND (col4.c3 <> col9.c3) AND (col4.c4 <> col5.c4) AND (col4.c4 <> col6.c4) AND (col4.c4 <> col7.c4) AND (col4.c4 <> col8.c4) AND (col4.c4 <> col9.c4) AND (col4.c5 <> col5.c5) AND (col4.c5 <> col6.c5) AND (col4.c5 <> col7.c5) AND (col4.c5 <> col8.c5) AND (col4.c5 <> col9.c5) AND (col4.c6 <> col5.c6) AND (col4.c6 <> col6.c6) AND (col4.c6 <> col7.c6) AND (col4.c6 <> col8.c6) AND (col4.c6 <> col9.c6) AND (col4.c7 <> col5.c7) AND (col4.c7 <> col6.c7) AND (col4.c7 <> col7.c7) AND (col4.c7 <> col8.c7) AND (col4.c7 <> col9.c7) AND
(col4.c8 <> col5.c8) AND (col4.c8 <> col6.c8) AND (col4.c8 <> col7.c8) AND (col4.c8 <> col8.c8) AND (col4.c8 <> col9.c8) AND (col4.c9 <> col5.c9) AND (col4.c9 <> col6.c9) AND (col4.c9 <> col7.c9) AND (col4.c9 <> col8.c9) AND (col4.c9 <> col9.c9) AND (col5.c1 <> col6.c1) AND (col5.c1 <> col7.c1) AND (col5.c1 <> col8.c1) AND (col5.c1 <> col9.c1) AND (col5.c2 <> col6.c2) AND (col5.c2 <> col7.c2) AND (col5.c2 <> col8.c2) AND (col5.c2 <> col9.c2) AND (col5.c3 <> col6.c3) AND (col5.c3 <> col7.c3) AND (col5.c3 <> col8.c3) AND (col5.c3 <> col9.c3) AND (col5.c4 <> col6.c4) AND (col5.c4 <> col7.c4) AND (col5.c4 <> col8.c4) AND (col5.c4 <> col9.c4) AND (col5.c5 <> col6.c5) AND (col5.c5 <> col7.c5) AND (col5.c5 <> col8.c5) AND (col5.c5 <> col9.c5) AND (col5.c6 <> col6.c6) AND (col5.c6 <> col7.c6) AND
(col5.c6 <> col8.c6) AND (col5.c6 <> col9.c6) AND (col5.c7 <> col6.c7) AND (col5.c7 <> col7.c7) AND (col5.c7 <> col8.c7) AND (col5.c7 <> col9.c7) AND (col5.c8 <> col6.c8) AND (col5.c8 <> col7.c8) AND (col5.c8 <> col8.c8) AND (col5.c8 <> col9.c8) AND (col5.c9 <> col6.c9) AND (col5.c9 <> col7.c9) AND (col5.c9 <> col8.c9) AND (col5.c9 <> col9.c9) AND (col6.c1 <> col7.c1) AND (col6.c1 <> col8.c1) AND (col6.c1 <> col9.c1) AND (col6.c2 <> col7.c2) AND (col6.c2 <> col8.c2) AND (col6.c2 <> col9.c2) AND (col6.c3 <> col7.c3) AND (col6.c3 <> col8.c3) AND (col6.c3 <> col9.c3) AND (col6.c4 <> col7.c4) AND (col6.c4 <> col8.c4) AND (col6.c4 <> col9.c4) AND (col6.c5 <> col7.c5) AND (col6.c5 <> col8.c5) AND (col6.c5 <> col9.c5) AND (col6.c6 <> col7.c6) AND (col6.c6 <> col8.c6) AND (col6.c6 <> col9.c6) AND
(col6.c7 <> col7.c7) AND (col6.c7 <> col8.c7) AND (col6.c7 <> col9.c7) AND (col6.c8 <> col7.c8) AND (col6.c8 <> col8.c8) AND (col6.c8 <> col9.c8) AND (col6.c9 <> col7.c9) AND (col6.c9 <> col8.c9) AND (col6.c9 <> col9.c9) AND (col7.c1 <> col8.c1) AND (col7.c1 <> col9.c1) AND (col7.c2 <> col8.c2) AND (col7.c2 <> col9.c2) AND (col7.c3 <> col8.c3) AND (col7.c3 <> col9.c3) AND (col7.c4 <> col8.c4) AND (col7.c4 <> col9.c4) AND (col7.c5 <> col8.c5) AND (col7.c5 <> col9.c5) AND (col7.c6 <> col8.c6) AND (col7.c6 <> col9.c6) AND (col7.c7 <> col8.c7) AND (col7.c7 <> col9.c7) AND (col7.c8 <> col8.c8) AND (col7.c8 <> col9.c8) AND (col7.c9 <> col8.c9) AND (col7.c9 <> col9.c9) AND (col8.c1 <> col9.c1) AND (col8.c2 <> col9.c2) AND (col8.c3 <> col9.c3) AND (col8.c4 <> col9.c4) AND (col8.c5 <> col9.c5) AND
(col8.c6 <> col9.c6) AND (col8.c7 <> col9.c7) AND (col8.c8 <> col9.c8) AND (col8.c9 <> col9.c9) AND
-- Nombres uniques dans chaque maison de 3x3
(col1.c1 <> col1.c2) AND (col1.c1 <> col1.c3) AND (col1.c1 <> col2.c2) AND (col1.c1 <> col2.c3) AND (col1.c1 <> col3.c2) AND (col1.c1 <> col3.c3) AND (col1.c2 <> col1.c3) AND (col1.c2 <> col2.c1) AND (col1.c2 <> col2.c3) AND (col1.c2 <> col3.c1) AND (col1.c2 <> col3.c3) AND (col1.c3 <> col2.c1) AND (col1.c3 <> col2.c2) AND (col1.c3 <> col3.c1) AND (col1.c3 <> col3.c2) AND (col1.c4 <> col1.c5) AND (col1.c4 <> col1.c6) AND (col1.c4 <> col2.c5) AND (col1.c4 <> col2.c6) AND (col1.c4 <> col3.c5) AND (col1.c4 <> col3.c6) AND (col1.c5 <> col1.c6) AND (col1.c5 <> col2.c4) AND (col1.c5 <> col2.c6) AND (col1.c5 <> col3.c4) AND (col1.c5 <> col3.c6) AND (col1.c6 <> col2.c4) AND (col1.c6 <> col2.c5) AND (col1.c6 <> col3.c4) AND (col1.c6 <> col3.c5) AND (col1.c7 <> col1.c8) AND (col1.c7 <> col1.c9) AND
(col1.c7 <> col2.c8) AND (col1.c7 <> col2.c9) AND (col1.c7 <> col3.c8) AND (col1.c7 <> col3.c9) AND (col1.c8 <> col1.c9) AND (col1.c8 <> col2.c7) AND (col1.c8 <> col2.c9) AND (col1.c8 <> col3.c7) AND (col1.c8 <> col3.c9) AND (col1.c9 <> col2.c7) AND (col1.c9 <> col2.c8) AND (col1.c9 <> col3.c7) AND (col1.c9 <> col3.c8) AND (col2.c1 <> col2.c2) AND (col2.c1 <> col2.c3) AND (col2.c1 <> col3.c2) AND (col2.c1 <> col3.c3) AND (col2.c2 <> col2.c3) AND (col2.c2 <> col3.c1) AND (col2.c2 <> col3.c3) AND (col2.c3 <> col3.c1) AND (col2.c3 <> col3.c2) AND (col2.c4 <> col2.c5) AND (col2.c4 <> col2.c6) AND (col2.c4 <> col3.c5) AND (col2.c4 <> col3.c6) AND (col2.c5 <> col2.c6) AND (col2.c5 <> col3.c4) AND (col2.c5 <> col3.c6) AND (col2.c6 <> col3.c4) AND (col2.c6 <> col3.c5) AND (col2.c7 <> col2.c8) AND
(col2.c7 <> col2.c9) AND (col2.c7 <> col3.c8) AND (col2.c7 <> col3.c9) AND (col2.c8 <> col2.c9) AND (col2.c8 <> col3.c7) AND (col2.c8 <> col3.c9) AND (col2.c9 <> col3.c7) AND (col2.c9 <> col3.c8) AND (col3.c1 <> col3.c2) AND (col3.c1 <> col3.c3) AND (col3.c2 <> col3.c3) AND (col3.c4 <> col3.c5) AND (col3.c4 <> col3.c6) AND (col3.c5 <> col3.c6) AND (col3.c7 <> col3.c8) AND (col3.c7 <> col3.c9) AND (col3.c8 <> col3.c9) AND (col4.c1 <> col4.c2) AND (col4.c1 <> col4.c3) AND (col4.c1 <> col5.c2) AND (col4.c1 <> col5.c3) AND (col4.c1 <> col6.c2) AND (col4.c1 <> col6.c3) AND (col4.c2 <> col4.c3) AND (col4.c2 <> col5.c1) AND (col4.c2 <> col5.c3) AND (col4.c2 <> col6.c1) AND (col4.c2 <> col6.c3) AND (col4.c3 <> col5.c1) AND (col4.c3 <> col5.c2) AND (col4.c3 <> col6.c1) AND (col4.c3 <> col6.c2) AND
(col4.c4 <> col4.c5) AND (col4.c4 <> col4.c6) AND (col4.c4 <> col5.c5) AND (col4.c4 <> col5.c6) AND (col4.c4 <> col6.c5) AND (col4.c4 <> col6.c6) AND (col4.c5 <> col4.c6) AND (col4.c5 <> col5.c4) AND (col4.c5 <> col5.c6) AND (col4.c5 <> col6.c4) AND (col4.c5 <> col6.c6) AND (col4.c6 <> col5.c4) AND (col4.c6 <> col5.c5) AND (col4.c6 <> col6.c4) AND (col4.c6 <> col6.c5) AND (col4.c7 <> col4.c8) AND (col4.c7 <> col4.c9) AND (col4.c7 <> col5.c8) AND (col4.c7 <> col5.c9) AND (col4.c7 <> col6.c8) AND (col4.c7 <> col6.c9) AND (col4.c8 <> col4.c9) AND (col4.c8 <> col5.c7) AND (col4.c8 <> col5.c9) AND (col4.c8 <> col6.c7) AND (col4.c8 <> col6.c9) AND (col4.c9 <> col5.c7) AND (col4.c9 <> col5.c8) AND (col4.c9 <> col6.c7) AND (col4.c9 <> col6.c8) AND (col5.c1 <> col5.c2) AND (col5.c1 <> col5.c3) AND
(col5.c1 <> col6.c2) AND (col5.c1 <> col6.c3) AND (col5.c2 <> col5.c3) AND (col5.c2 <> col6.c1) AND (col5.c2 <> col6.c3) AND (col5.c3 <> col6.c1) AND (col5.c3 <> col6.c2) AND (col5.c4 <> col5.c5) AND (col5.c4 <> col5.c6) AND (col5.c4 <> col6.c5) AND (col5.c4 <> col6.c6) AND (col5.c5 <> col5.c6) AND (col5.c5 <> col6.c4) AND (col5.c5 <> col6.c6) AND (col5.c6 <> col6.c4) AND (col5.c6 <> col6.c5) AND (col5.c7 <> col5.c8) AND (col5.c7 <> col5.c9) AND (col5.c7 <> col6.c8) AND (col5.c7 <> col6.c9) AND (col5.c8 <> col5.c9) AND (col5.c8 <> col6.c7) AND (col5.c8 <> col6.c9) AND (col5.c9 <> col6.c7) AND (col5.c9 <> col6.c8) AND (col6.c1 <> col6.c2) AND (col6.c1 <> col6.c3) AND (col6.c2 <> col6.c3) AND (col6.c4 <> col6.c5) AND (col6.c4 <> col6.c6) AND (col6.c5 <> col6.c6) AND (col6.c7 <> col6.c8) AND
(col6.c7 <> col6.c9) AND (col6.c8 <> col6.c9) AND (col7.c1 <> col7.c2) AND (col7.c1 <> col7.c3) AND (col7.c1 <> col8.c2) AND (col7.c1 <> col8.c3) AND (col7.c1 <> col9.c2) AND (col7.c1 <> col9.c3) AND (col7.c2 <> col7.c3) AND (col7.c2 <> col8.c1) AND (col7.c2 <> col8.c3) AND (col7.c2 <> col9.c1) AND (col7.c2 <> col9.c3) AND (col7.c3 <> col8.c1) AND (col7.c3 <> col8.c2) AND (col7.c3 <> col9.c1) AND (col7.c3 <> col9.c2) AND (col7.c4 <> col7.c5) AND (col7.c4 <> col7.c6) AND (col7.c4 <> col8.c5) AND (col7.c4 <> col8.c6) AND (col7.c4 <> col9.c5) AND (col7.c4 <> col9.c6) AND (col7.c5 <> col7.c6) AND (col7.c5 <> col8.c4) AND (col7.c5 <> col8.c6) AND (col7.c5 <> col9.c4) AND (col7.c5 <> col9.c6) AND (col7.c6 <> col8.c4) AND (col7.c6 <> col8.c5) AND (col7.c6 <> col9.c4) AND (col7.c6 <> col9.c5) AND
(col7.c7 <> col7.c8) AND (col7.c7 <> col7.c9) AND (col7.c7 <> col8.c8) AND (col7.c7 <> col8.c9) AND (col7.c7 <> col9.c8) AND (col7.c7 <> col9.c9) AND (col7.c8 <> col7.c9) AND (col7.c8 <> col8.c7) AND (col7.c8 <> col8.c9) AND (col7.c8 <> col9.c7) AND (col7.c8 <> col9.c9) AND (col7.c9 <> col8.c7) AND (col7.c9 <> col8.c8) AND (col7.c9 <> col9.c7) AND (col7.c9 <> col9.c8) AND (col8.c1 <> col8.c2) AND (col8.c1 <> col8.c3) AND (col8.c1 <> col9.c2) AND (col8.c1 <> col9.c3) AND (col8.c2 <> col8.c3) AND (col8.c2 <> col9.c1) AND (col8.c2 <> col9.c3) AND (col8.c3 <> col9.c1) AND (col8.c3 <> col9.c2) AND (col8.c4 <> col8.c5) AND (col8.c4 <> col8.c6) AND (col8.c4 <> col9.c5) AND (col8.c4 <> col9.c6) AND (col8.c5 <> col8.c6) AND (col8.c5 <> col9.c4) AND (col8.c5 <> col9.c6) AND (col8.c6 <> col9.c4) AND
(col8.c6 <> col9.c5) AND (col8.c7 <> col8.c8) AND (col8.c7 <> col8.c9) AND (col8.c7 <> col9.c8) AND (col8.c7 <> col9.c9) AND (col8.c8 <> col8.c9) AND (col8.c8 <> col9.c7) AND (col8.c8 <> col9.c9) AND (col8.c9 <> col9.c7) AND (col8.c9 <> col9.c8) AND (col9.c1 <> col9.c2) AND (col9.c1 <> col9.c3) AND (col9.c2 <> col9.c3) AND (col9.c4 <> col9.c5) AND (col9.c4 <> col9.c6) AND (col9.c5 <> col9.c6) AND (col9.c7 <> col9.c8) AND (col9.c7 <> col9.c9) AND (col9.c8 <> col9.c9);

Finalement, la vue combinée.

USE sudoku;

DROP VIEW IF EXISTS sudoku_memory_combined_view;
CREATE VIEW sudoku_memory_combined_view AS
SELECT t1.*
FROM sudoku_memory_rows_view t1
INNER JOIN sudoku_memory_columns_view t2
ON

-- Jointures entre représentation-colonnes et représentation-rangées
(t1.r1c1 = t2.r1c1) AND (t1.r1c2 = t2.r1c2) AND (t1.r1c3 = t2.r1c3) AND (t1.r1c4 = t2.r1c4) AND
(t1.r1c5 = t2.r1c5) AND (t1.r1c6 = t2.r1c6) AND (t1.r1c7 = t2.r1c7) AND (t1.r1c8 = t2.r1c8) AND
(t1.r1c9 = t2.r1c9) AND (t1.r2c1 = t2.r2c1) AND (t1.r2c2 = t2.r2c2) AND (t1.r2c3 = t2.r2c3) AND
(t1.r2c4 = t2.r2c4) AND (t1.r2c5 = t2.r2c5) AND (t1.r2c6 = t2.r2c6) AND (t1.r2c7 = t2.r2c7) AND
(t1.r2c8 = t2.r2c8) AND (t1.r2c9 = t2.r2c9) AND (t1.r3c1 = t2.r3c1) AND (t1.r3c2 = t2.r3c2) AND
(t1.r3c3 = t2.r3c3) AND (t1.r3c4 = t2.r3c4) AND (t1.r3c5 = t2.r3c5) AND (t1.r3c6 = t2.r3c6) AND
(t1.r3c7 = t2.r3c7) AND (t1.r3c8 = t2.r3c8) AND (t1.r3c9 = t2.r3c9) AND (t1.r4c1 = t2.r4c1) AND
(t1.r4c2 = t2.r4c2) AND (t1.r4c3 = t2.r4c3) AND (t1.r4c4 = t2.r4c4) AND (t1.r4c5 = t2.r4c5) AND
(t1.r4c6 = t2.r4c6) AND (t1.r4c7 = t2.r4c7) AND (t1.r4c8 = t2.r4c8) AND (t1.r4c9 = t2.r4c9) AND
(t1.r5c1 = t2.r5c1) AND (t1.r5c2 = t2.r5c2) AND (t1.r5c3 = t2.r5c3) AND (t1.r5c4 = t2.r5c4) AND
(t1.r5c5 = t2.r5c5) AND (t1.r5c6 = t2.r5c6) AND (t1.r5c7 = t2.r5c7) AND (t1.r5c8 = t2.r5c8) AND
(t1.r5c9 = t2.r5c9) AND (t1.r6c1 = t2.r6c1) AND (t1.r6c2 = t2.r6c2) AND (t1.r6c3 = t2.r6c3) AND
(t1.r6c4 = t2.r6c4) AND (t1.r6c5 = t2.r6c5) AND (t1.r6c6 = t2.r6c6) AND (t1.r6c7 = t2.r6c7) AND
(t1.r6c8 = t2.r6c8) AND (t1.r6c9 = t2.r6c9) AND (t1.r7c1 = t2.r7c1) AND (t1.r7c2 = t2.r7c2) AND
(t1.r7c3 = t2.r7c3) AND (t1.r7c4 = t2.r7c4) AND (t1.r7c5 = t2.r7c5) AND (t1.r7c6 = t2.r7c6) AND
(t1.r7c7 = t2.r7c7) AND (t1.r7c8 = t2.r7c8) AND (t1.r7c9 = t2.r7c9) AND (t1.r8c1 = t2.r8c1) AND
(t1.r8c2 = t2.r8c2) AND (t1.r8c3 = t2.r8c3) AND (t1.r8c4 = t2.r8c4) AND (t1.r8c5 = t2.r8c5) AND
(t1.r8c6 = t2.r8c6) AND (t1.r8c7 = t2.r8c7) AND (t1.r8c8 = t2.r8c8) AND (t1.r8c9 = t2.r8c9) AND
(t1.r9c1 = t2.r9c1) AND (t1.r9c2 = t2.r9c2) AND (t1.r9c3 = t2.r9c3) AND (t1.r9c4 = t2.r9c4) AND
(t1.r9c5 = t2.r9c5) AND (t1.r9c6 = t2.r9c6) AND (t1.r9c7 = t2.r9c7) AND (t1.r9c8 = t2.r9c8) AND
(t1.r9c9 = t2.r9c9);

Réessayons l’exemple du début de cet article pour comparer :


mysql> SELECT *
 -> FROM sudoku_memory_combined_view
 -> WHERE
 -> (r2c2 = 3) AND (r2c3 = 4) AND (r2c4 = 8) AND (r2c5 = 2) AND
 -> (r2c6 = 5) AND (r2c7 = 6) AND (r2c8 = 9) AND (r3c2 = 5) AND
 -> (r3c3 = 9) AND (r3c4 = 3) AND (r3c5 = 6) AND (r3c6 = 4) AND
 -> (r3c7 = 1) AND (r3c8 = 8) AND (r4c2 = 9) AND (r4c3 = 7) AND
 -> (r4c4 = 1) AND (r4c5 = 8) AND (r4c6 = 2) AND (r4c7 = 5) AND
 -> (r4c8 = 6) AND (r6c2 = 8) AND (r6c3 = 1) AND (r6c4 = 4) AND
 -> (r6c5 = 7) AND (r6c6 = 6) AND (r6c7 = 2) AND (r6c8 = 3) AND
 -> (r7c2 = 2) AND (r7c3 = 5) AND (r7c4 = 6) AND (r7c5 = 4) AND
 -> (r7c6 = 1) AND (r7c7 = 9) AND (r7c8 = 7) AND (r8c2 = 7) AND
 -> (r8c3 = 6) AND (r8c4 = 5) AND (r8c5 = 3) AND (r8c6 = 8) AND
 -> (r8c7 = 4) AND (r8c8 = 2);
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| r1c1 | r1c2 | r1c3 | r1c4 | r1c5 | r1c6 | r1c7 | r1c8 | r1c9 | r2c1 | r2c2 | r2c3 | r2c4 | r2c5 | r2c6 | r2c7 | r2c8 | r2c9 | r3c1 | r3c2 | r3c3 | r3c4 | r3c5 | r3c6 | r3c7 | r3c8 | r3c9 | r4c1 | r4c2 | r4c3 | r4c4 | r4c5 | r4c6 | r4c7 | r4c8 | r4c9 | r5c1 | r5c2 | r5c3 | r5c4 | r5c5 | r5c6 | r5c7 | r5c8 | r5c9 | r6c1 | r6c2 | r6c3 | r6c4 | r6c5 | r6c6 | r6c7 | r6c8 | r6c9 | r7c1 | r7c2 | r7c3 | r7c4 | r7c5 | r7c6 | r7c7 | r7c8 | r7c9 | r8c1 | r8c2 | r8c3 | r8c4 | r8c5 | r8c6 | r8c7 | r8c8 | r8c9 | r9c1 | r9c2 | r9c3 | r9c4 | r9c5 | r9c6 | r9c7 | r9c8 | r9c9 |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
|   2  |   6  |   8  |   7  |   1  |   9  |   3  |   4  |   5  |   1  |   3  |   4  |   8  |   2  |   5  |   6  |   9  |   7  |   7  |   5  |   9  |   3  |   6  |   4  |   1  |   8  |   2  |   3  |   9  |   7  |   1  |   8  |   2  |   5  |   6  |   4  |   6  |   4  |   2  |   9  |   5  |   3  |   7  |   1  |   8  |   5  |   8  |   1  |   4  |   7  |   6  |   2  |   3  |   9  |   8  |   2  |   5  |   6  |   4  |   1  |   9  |   7  |   3  |   9  |   7  |   6  |   5  |   3  |   8  |   4  |   2  |   1  |   4  |   1  |   3  |   2  |   9  |   7  |   8  |   5  |   6  |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
1 row in set (0.55 sec)

Wow! Nous sommes passés de 1.5 à 0.55 seconde! Maintenant, qu’en est-il de notre grille à 17 révélés ?

mysql> SELECT *
-> FROM sudoku_memory_combined_view
-> WHERE
-> (r1c8 = 1) AND
-> (r2c1 = 4) AND
-> (r3c2 = 2) AND
-> (r4c5 = 5) AND
-> (r4c7 = 4) AND
-> (r4c9 = 7) AND
-> (r5c3 = 8) AND
-> (r5c7 = 3) AND
-> (r6c3 = 1) AND
-> (r6c5 = 9) AND
-> (r7c1 = 3) AND
-> (r7c4 = 4) AND
-> (r7c7 = 2) AND
-> (r8c2 = 5) AND
-> (r8c4 = 1) AND
-> (r9c4 = 8) AND
-> (r9c6 = 6);
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| r1c1 | r1c2 | r1c3 | r1c4 | r1c5 | r1c6 | r1c7 | r1c8 | r1c9 | r2c1 | r2c2 | r2c3 | r2c4 | r2c5 | r2c6 | r2c7 | r2c8 | r2c9 | r3c1 | r3c2 | r3c3 | r3c4 | r3c5 | r3c6 | r3c7 | r3c8 | r3c9 | r4c1 | r4c2 | r4c3 | r4c4 | r4c5 | r4c6 | r4c7 | r4c8 | r4c9 | r5c1 | r5c2 | r5c3 | r5c4 | r5c5 | r5c6 | r5c7 | r5c8 | r5c9 | r6c1 | r6c2 | r6c3 | r6c4 | r6c5 | r6c6 | r6c7 | r6c8 | r6c9 | r7c1 | r7c2 | r7c3 | r7c4 | r7c5 | r7c6 | r7c7 | r7c8 | r7c9 | r8c1 | r8c2 | r8c3 | r8c4 | r8c5 | r8c6 | r8c7 | r8c8 | r8c9 | r9c1 | r9c2 | r9c3 | r9c4 | r9c5 | r9c6 | r9c7 | r9c8 | r9c9 |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
|    6 |    9 |    3 |    7 |    8 |    4 |    5 |    1 |    2 |    4 |    8 |    7 |    5 |    1 |    2 |    9 |    3 |    6 |    1 |    2 |    5 |    9 |    6 |    3 |    8 |    7 |    4 |    9 |    3 |    2 |    6 |    5 |    1 |    4 |    8 |    7 |    5 |    6 |    8 |    2 |    4 |    7 |    3 |    9 |    1 |    7 |    4 |    1 |    3 |    9 |    8 |    6 |    2 |    5 |    3 |    1 |    9 |    4 |    7 |    5 |    2 |    6 |    8 |    8 |    5 |    6 |    1 |    2 |    9 |    7 |    4 |    3 |    2 |    7 |    4 |    8 |    3 |    6 |    1 |    5 |    9 |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
1 row in set (7.41 sec)

sudoku17clues

Fantastique!  Nous sommes passés de 20 minutes à 7 secondes!  Mais il y a encore place à amélioration!

5. Presser encore plus fort

Maintenant que nous sommes en mesure d’obtenir des résultats dans des temps raisonnables en utilisant une table de type MEMORY, nous pouvons regarder du côté des variables système pour essayer de les optimiser.

Mais avant de se lancer dans cette entreprise, il importe d’avoir un jeu d’essai afin d’effectuer des tests reproduisibles et mesurables pour vérifier l’impact de chacun des changements sur ces variables.

Nous allons tout d’abord créer une table qui nous permettra de sauvegarder le temps d’exécution de toutes les grilles de notre jeu d’essai.

DROP TABLE IF EXISTS tests;

CREATE TABLE tests (
debut DATETIME,
fin DATETIME
) ENGINE=MYISAM;

Maintenant, nous allons créer notre jeu d’essai.  Évidemment notre échantillon de grilles est varié de façon à être représentatif afin  de mesurer chaque option de façon précise.

USE sudoku;
TRUNCATE tests;
INSERT INTO tests(debut, fin) VALUES (NOW(), NULL);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 1) AND (r1c3 = 3) AND (r1c4 = 7) AND (r1c9 = 5) AND (r2c4 = 6) AND (r2c6 = 4) AND (r3c1 = 8) AND (r4c4 = 8) AND (r4c5 = 1) AND (r5c2 = 9) AND (r5c7 = 7) AND (r6c2 = 6) AND (r6c8 = 9) AND (r7c2 = 2) AND (r7c7 = 4) AND (r8c1 = 5) AND (r8c5 = 3) AND (r9c8 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 8) AND (r1c4 = 3) AND (r1c6 = 7) AND (r2c3 = 9) AND (r3c1 = 2) AND (r3c2 = 7) AND (r3c5 = 4) AND (r4c2 = 3) AND (r4c5 = 1) AND (r5c1 = 4) AND (r5c4 = 9) AND (r5c7 = 2) AND (r5c8 = 8) AND (r6c4 = 6) AND (r6c6 = 2) AND (r6c7 = 4) AND (r6c8 = 3) AND (r7c1 = 3) AND (r7c2 = 1) AND (r7c6 = 6) AND (r8c1 = 6) AND (r8c3 = 8) AND (r8c4 = 1) AND (r8c9 = 7) AND (r9c5 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 2) AND (r1c8 = 1) AND (r2c6 = 2) AND (r2c8 = 3) AND (r2c9 = 4) AND (r3c3 = 3) AND (r3c5 = 5) AND (r4c4 = 4) AND (r4c8 = 6) AND (r5c3 = 2) AND (r5c7 = 9) AND (r6c2 = 5) AND (r6c6 = 8) AND (r7c5 = 3) AND (r7c7 = 5) AND (r8c1 = 7) AND (r8c2 = 9) AND (r8c4 = 1) AND (r9c2 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r2c2 = 8) AND (r3c5 = 5) AND (r3c6 = 3) AND (r3c8 = 8) AND (r3c9 = 9) AND (r4c2 = 2) AND (r4c3 = 4) AND (r4c6 = 9) AND (r5c5 = 1) AND (r5c9 = 5) AND (r6c2 = 1) AND (r6c6 = 7) AND (r7c3 = 2) AND (r7c4 = 1) AND (r7c7 = 3) AND (r8c1 = 9) AND (r8c6 = 5) AND (r8c9 = 7) AND (r9c1 = 5) AND (r9c5 = 8) AND (r9c8 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 5) AND (r1c6 = 8) AND (r1c7 = 6) AND (r2c6 = 6) AND (r2c7 = 2) AND (r2c8 = 7) AND (r3c2 = 1) AND (r4c1 = 9) AND (r4c4 = 7) AND (r4c5 = 6) AND (r4c6 = 2) AND (r5c1 = 7) AND (r6c3 = 8) AND (r7c1 = 2) AND (r7c3 = 3) AND (r7c7 = 8) AND (r8c4 = 1) AND (r8c5 = 9) AND (r8c9 = 5) AND (r9c3 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 5) AND (r1c4 = 8) AND (r1c5 = 3) AND (r2c7 = 7) AND (r2c8 = 1) AND (r3c2 = 3) AND (r4c1 = 7) AND (r4c4 = 4) AND (r4c7 = 8) AND (r5c1 = 1) AND (r5c3 = 2) AND (r7c2 = 8) AND (r7c4 = 6) AND (r7c7 = 4) AND (r8c1 = 9) AND (r8c6 = 2) AND (r9c5 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 7) AND (r1c9 = 5) AND (r2c2 = 3) AND (r2c8 = 7) AND (r3c1 = 2) AND (r3c3 = 5) AND (r3c8 = 3) AND (r3c9 = 8) AND (r4c8 = 8) AND (r4c9 = 9) AND (r5c1 = 5) AND (r5c3 = 8) AND (r5c4 = 2) AND (r5c6 = 9) AND (r5c7 = 7) AND (r5c9 = 4) AND (r6c1 = 3) AND (r7c1 = 6) AND (r7c3 = 4) AND (r7c4 = 9) AND (r7c5 = 8) AND (r7c6 = 7) AND (r7c7 = 5) AND (r8c1 = 9) AND (r8c4 = 5) AND (r9c4 = 4) AND (r9c6 = 6) AND (r9c9 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 4) AND (r1c2 = 6) AND (r1c3 = 8) AND (r1c7 = 1) AND (r2c2 = 7) AND (r2c4 = 4) AND (r2c6 = 8) AND (r2c8 = 5) AND (r3c4 = 6) AND (r4c3 = 6) AND (r4c4 = 1) AND (r4c5 = 8) AND (r4c6 = 3) AND (r4c9 = 7) AND (r5c3 = 7) AND (r6c1 = 3) AND (r6c5 = 5) AND (r6c7 = 2) AND (r6c9 = 1) AND (r7c6 = 7) AND (r8c4 = 8) AND (r8c6 = 2) AND (r8c7 = 5) AND (r9c6 = 5) AND (r9c7 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 9) AND (r1c8 = 1) AND (r2c6 = 2) AND (r2c8 = 3) AND (r2c9 = 4) AND (r3c3 = 5) AND (r3c5 = 6) AND (r4c4 = 3) AND (r4c8 = 7) AND (r5c3 = 2) AND (r5c7 = 6) AND (r6c2 = 1) AND (r6c6 = 5) AND (r7c5 = 8) AND (r7c7 = 2) AND (r8c1 = 7) AND (r8c2 = 3) AND (r8c4 = 9) AND (r9c2 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c6 = 7) AND (r1c9 = 2) AND (r2c5 = 4) AND (r2c6 = 5) AND (r2c8 = 7) AND (r3c3 = 9) AND (r4c1 = 3) AND (r4c5 = 5) AND (r4c7 = 8) AND (r5c1 = 4) AND (r5c2 = 8) AND (r5c4 = 9) AND (r5c6 = 1) AND (r5c9 = 7) AND (r6c3 = 7) AND (r6c6 = 4) AND (r6c7 = 2) AND (r6c9 = 9) AND (r7c5 = 1) AND (r7c7 = 3) AND (r8c8 = 5) AND (r9c2 = 3) AND (r9c4 = 8) AND (r9c5 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 9) AND (r1c8 = 7) AND (r2c8 = 2) AND (r2c9 = 4) AND (r3c1 = 1) AND (r4c2 = 2) AND (r4c3 = 9) AND (r4c9 = 5) AND (r5c6 = 1) AND (r5c7 = 6) AND (r6c2 = 4) AND (r6c5 = 8) AND (r7c4 = 4) AND (r7c5 = 3) AND (r8c1 = 5) AND (r8c7 = 8) AND (r9c4 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r2c2 = 9) AND (r2c3 = 3) AND (r3c2 = 7) AND (r3c8 = 3) AND (r4c3 = 9) AND (r4c5 = 6) AND (r4c8 = 7) AND (r4c9 = 4) AND (r5c3 = 6) AND (r5c5 = 7) AND (r5c7 = 3) AND (r5c8 = 9) AND (r6c2 = 3) AND (r6c4 = 5) AND (r6c7 = 6) AND (r6c8 = 8) AND (r7c1 = 9) AND (r7c5 = 8) AND (r7c6 = 2) AND (r7c7 = 4) AND (r8c2 = 8) AND (r8c3 = 2) AND (r8c5 = 3) AND (r8c8 = 5) AND (r8c9 = 7) AND (r9c2 = 6) AND (r9c3 = 4) AND (r9c4 = 7) AND (r9c5 = 5) AND (r9c8 = 2) AND (r9c9 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 7) AND (r1c5 = 5) AND (r1c8 = 6) AND (r1c9 = 9) AND (r2c1 = 6) AND (r2c8 = 4) AND (r3c2 = 1) AND (r3c5 = 8) AND (r3c6 = 9) AND (r3c9 = 3) AND (r4c4 = 1) AND (r5c4 = 3) AND (r6c2 = 8) AND (r6c8 = 9) AND (r7c1 = 4) AND (r7c2 = 6) AND (r8c3 = 7) AND (r8c6 = 3) AND (r8c9 = 8) AND (r9c2 = 5) AND (r9c3 = 8) AND (r9c4 = 7) AND (r9c6 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 7) AND (r1c5 = 9) AND (r1c6 = 4) AND (r2c2 = 1) AND (r2c6 = 7) AND (r3c3 = 9) AND (r3c4 = 2) AND (r3c5 = 1) AND (r4c1 = 2) AND (r4c4 = 5) AND (r4c6 = 9) AND (r5c3 = 8) AND (r5c4 = 6) AND (r6c1 = 9) AND (r6c2 = 5) AND (r6c6 = 1) AND (r6c8 = 2) AND (r6c9 = 7) AND (r7c1 = 8) AND (r7c6 = 2) AND (r7c7 = 6) AND (r8c1 = 1) AND (r8c5 = 5) AND (r8c6 = 8) AND (r8c9 = 2) AND (r9c4 = 7) AND (r9c5 = 4) AND (r9c9 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 1) AND (r1c4 = 6) AND (r1c5 = 2) AND (r2c1 = 5) AND (r2c8 = 4) AND (r2c9 = 3) AND (r3c5 = 9) AND (r4c1 = 7) AND (r4c8 = 8) AND (r5c3 = 5) AND (r5c9 = 4) AND (r6c4 = 1) AND (r7c6 = 3) AND (r7c7 = 6) AND (r8c2 = 9) AND (r8c7 = 2) AND (r9c1 = 8) AND (r9c6 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 5) AND (r1c3 = 8) AND (r1c6 = 6) AND (r1c7 = 3) AND (r1c8 = 2) AND (r1c9 = 4) AND (r2c1 = 9) AND (r2c2 = 2) AND (r2c3 = 3) AND (r2c6 = 8) AND (r2c7 = 5) AND (r2c8 = 6) AND (r3c5 = 5) AND (r4c9 = 8) AND (r5c2 = 8) AND (r5c3 = 7) AND (r5c6 = 9) AND (r7c2 = 4) AND (r7c4 = 6) AND (r7c6 = 7) AND (r7c8 = 5) AND (r8c1 = 3) AND (r8c5 = 9) AND (r8c6 = 5) AND (r8c8 = 8) AND (r8c9 = 2) AND (r9c2 = 9) AND (r9c3 = 5) AND (r9c5 = 8) AND (r9c7 = 6) AND (r9c8 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 3) AND (r1c5 = 7) AND (r1c7 = 8) AND (r2c4 = 4) AND (r2c6 = 3) AND (r3c1 = 2) AND (r3c4 = 5) AND (r3c5 = 6) AND (r3c6 = 8) AND (r3c9 = 3) AND (r4c2 = 6) AND (r4c3 = 2) AND (r4c7 = 5) AND (r4c8 = 3) AND (r5c1 = 1) AND (r5c3 = 5) AND (r5c7 = 9) AND (r5c9 = 4) AND (r6c2 = 3) AND (r6c3 = 9) AND (r6c7 = 2) AND (r6c8 = 1) AND (r7c1 = 3) AND (r7c4 = 6) AND (r7c5 = 2) AND (r7c6 = 7) AND (r7c9 = 5) AND (r8c4 = 9) AND (r8c6 = 5) AND (r9c3 = 7) AND (r9c5 = 8) AND (r9c7 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 3) AND (r1c3 = 8) AND (r2c1 = 7) AND (r2c6 = 8) AND (r3c1 = 6) AND (r3c2 = 4) AND (r3c3 = 9) AND (r3c4 = 3) AND (r3c5 = 1) AND (r3c6 = 7) AND (r3c8 = 2) AND (r4c1 = 1) AND (r4c2 = 7) AND (r4c5 = 3) AND (r4c6 = 6) AND (r4c8 = 8) AND (r4c9 = 2) AND (r5c1 = 3) AND (r5c3 = 6) AND (r5c4 = 2) AND (r5c6 = 1) AND (r5c8 = 7) AND (r5c9 = 9) AND (r6c5 = 7) AND (r7c1 = 4) AND (r7c2 = 9) AND (r7c8 = 1) AND (r8c2 = 6) AND (r8c3 = 1) AND (r8c5 = 9) AND (r8c8 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c6 = 5) AND (r1c8 = 8) AND (r2c2 = 1) AND (r2c6 = 3) AND (r3c1 = 3) AND (r3c3 = 7) AND (r3c4 = 6) AND (r4c2 = 9) AND (r4c4 = 1) AND (r4c5 = 7) AND (r4c6 = 6) AND (r4c7 = 3) AND (r5c4 = 9) AND (r5c6 = 8) AND (r5c8 = 1) AND (r6c1 = 2) AND (r7c2 = 6) AND (r8c2 = 8) AND (r8c6 = 1) AND (r8c8 = 6) AND (r9c2 = 3) AND (r9c4 = 2) AND (r9c9 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 8) AND (r1c7 = 4) AND (r1c9 = 3) AND (r2c1 = 9) AND (r2c4 = 3) AND (r2c7 = 7) AND (r3c2 = 1) AND (r3c3 = 5) AND (r3c6 = 2) AND (r4c1 = 6) AND (r4c8 = 9) AND (r4c9 = 5) AND (r5c2 = 3) AND (r5c3 = 7) AND (r6c4 = 8) AND (r7c7 = 8) AND (r7c8 = 3) AND (r7c9 = 2) AND (r8c2 = 2) AND (r8c5 = 9) AND (r9c1 = 8) AND (r9c4 = 7) AND (r9c9 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 7) AND (r1c4 = 2) AND (r1c6 = 4) AND (r1c8 = 5) AND (r2c2 = 4) AND (r2c9 = 2) AND (r3c2 = 2) AND (r3c5 = 8) AND (r3c9 = 6) AND (r4c3 = 7) AND (r4c9 = 5) AND (r5c1 = 8) AND (r5c4 = 5) AND (r6c1 = 6) AND (r6c3 = 3) AND (r6c8 = 7) AND (r7c3 = 9) AND (r7c4 = 7) AND (r8c1 = 3) AND (r8c3 = 2) AND (r8c5 = 5) AND (r8c8 = 6) AND (r9c3 = 5) AND (r9c4 = 3) AND (r9c7 = 9) AND (r9c8 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c7 = 8) AND (r1c8 = 7) AND (r2c1 = 2) AND (r2c2 = 6) AND (r3c2 = 4) AND (r3c5 = 6) AND (r3c6 = 5) AND (r4c3 = 7) AND (r5c6 = 2) AND (r5c8 = 3) AND (r6c6 = 3) AND (r6c8 = 4) AND (r6c9 = 5) AND (r7c4 = 3) AND (r8c3 = 2) AND (r8c4 = 8) AND (r8c5 = 9) AND (r8c6 = 7) AND (r9c2 = 5) AND (r9c9 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 3) AND (r1c5 = 8) AND (r1c8 = 7) AND (r1c9 = 1) AND (r2c2 = 6) AND (r2c3 = 7) AND (r3c1 = 8) AND (r5c1 = 7) AND (r5c2 = 2) AND (r5c3 = 9) AND (r5c5 = 3) AND (r5c6 = 1) AND (r5c8 = 6) AND (r5c9 = 4) AND (r6c1 = 3) AND (r6c2 = 8) AND (r6c3 = 1) AND (r7c3 = 8) AND (r7c5 = 1) AND (r7c7 = 7) AND (r7c8 = 4) AND (r8c2 = 1) AND (r8c3 = 2) AND (r8c4 = 6) AND (r8c8 = 8) AND (r8c9 = 3) AND (r9c1 = 6) AND (r9c4 = 3) AND (r9c5 = 4) AND (r9c8 = 1) AND (r9c9 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c8 = 4) AND (r2c5 = 8) AND (r2c9 = 7) AND (r3c4 = 1) AND (r3c5 = 4) AND (r3c6 = 6) AND (r3c7 = 9) AND (r3c9 = 8) AND (r4c1 = 2) AND (r4c5 = 6) AND (r4c9 = 3) AND (r5c3 = 1) AND (r5c5 = 9) AND (r5c9 = 6) AND (r6c2 = 8) AND (r6c3 = 6) AND (r6c4 = 3) AND (r6c5 = 7) AND (r6c7 = 4) AND (r7c5 = 1) AND (r7c7 = 7) AND (r8c1 = 9) AND (r8c2 = 4) AND (r8c8 = 3) AND (r8c9 = 1) AND (r9c6 = 7) AND (r9c9 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 3) AND (r1c5 = 2) AND (r1c6 = 6) AND (r2c7 = 4) AND (r2c9 = 1) AND (r3c1 = 5) AND (r4c1 = 2) AND (r4c8 = 6) AND (r5c6 = 5) AND (r5c8 = 3) AND (r6c2 = 4) AND (r6c4 = 1) AND (r7c4 = 4) AND (r7c5 = 1) AND (r7c7 = 7) AND (r8c4 = 8) AND (r9c1 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 4) AND (r1c7 = 8) AND (r1c8 = 1) AND (r2c1 = 9) AND (r2c4 = 6) AND (r2c6 = 7) AND (r3c3 = 8) AND (r3c6 = 2) AND (r3c8 = 6) AND (r4c6 = 1) AND (r4c8 = 4) AND (r4c9 = 2) AND (r5c2 = 3) AND (r6c1 = 6) AND (r6c2 = 4) AND (r7c1 = 8) AND (r7c2 = 1) AND (r8c7 = 4) AND (r8c8 = 3) AND (r9c3 = 7) AND (r9c4 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 3) AND (r1c3 = 4) AND (r1c6 = 5) AND (r1c8 = 8) AND (r2c2 = 5) AND (r2c5 = 9) AND (r2c8 = 4) AND (r2c9 = 3) AND (r3c1 = 9) AND (r3c2 = 8) AND (r3c4 = 2) AND (r3c9 = 5) AND (r4c1 = 3) AND (r4c5 = 7) AND (r4c9 = 8) AND (r5c2 = 4) AND (r5c6 = 3) AND (r5c7 = 6) AND (r5c8 = 9) AND (r6c2 = 9) AND (r6c5 = 6) AND (r6c7 = 2) AND (r7c1 = 6) AND (r7c5 = 5) AND (r7c6 = 7) AND (r8c5 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 2) AND (r1c5 = 5) AND (r1c6 = 4) AND (r1c7 = 3) AND (r1c8 = 6) AND (r1c9 = 1) AND (r2c4 = 2) AND (r3c5 = 1) AND (r3c6 = 9) AND (r4c4 = 4) AND (r4c6 = 8) AND (r5c2 = 4) AND (r5c4 = 3) AND (r5c5 = 2) AND (r5c6 = 5) AND (r5c7 = 1) AND (r5c8 = 8) AND (r6c5 = 6) AND (r6c8 = 9) AND (r6c9 = 4) AND (r7c1 = 3) AND (r7c4 = 1) AND (r7c6 = 2) AND (r7c9 = 5) AND (r8c9 = 3) AND (r9c6 = 6) AND (r9c7 = 2) AND (r9c8 = 1) AND (r9c9 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 1) AND (r1c5 = 6) AND (r2c2 = 3) AND (r2c7 = 5) AND (r2c9 = 4) AND (r3c5 = 2) AND (r4c8 = 7) AND (r4c9 = 2) AND (r5c3 = 1) AND (r5c4 = 5) AND (r5c5 = 7) AND (r5c7 = 9) AND (r6c2 = 4) AND (r6c8 = 1) AND (r7c2 = 9) AND (r7c3 = 2) AND (r8c4 = 7) AND (r8c7 = 6) AND (r8c8 = 3) AND (r9c8 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 8) AND (r1c3 = 5) AND (r1c9 = 2) AND (r2c4 = 9) AND (r2c6 = 1) AND (r3c1 = 3) AND (r4c2 = 6) AND (r4c4 = 7) AND (r4c7 = 4) AND (r5c1 = 2) AND (r5c5 = 5) AND (r6c8 = 6) AND (r7c4 = 3) AND (r7c5 = 8) AND (r8c2 = 1) AND (r8c7 = 7) AND (r9c2 = 4) AND (r9c8 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r2c2 = 7) AND (r2c7 = 8) AND (r2c9 = 4) AND (r3c5 = 9) AND (r3c6 = 8) AND (r3c7 = 3) AND (r3c9 = 2) AND (r4c1 = 6) AND (r4c4 = 1) AND (r4c7 = 9) AND (r5c3 = 7) AND (r5c8 = 3) AND (r6c1 = 2) AND (r6c2 = 8) AND (r6c6 = 3) AND (r6c7 = 6) AND (r7c2 = 3) AND (r7c4 = 9) AND (r7c5 = 4) AND (r7c6 = 6) AND (r7c9 = 8) AND (r8c2 = 2) AND (r9c1 = 1) AND (r9c3 = 4) AND (r9c4 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 6) AND (r1c8 = 1) AND (r2c6 = 2) AND (r2c8 = 3) AND (r2c9 = 4) AND (r3c3 = 2) AND (r3c5 = 5) AND (r4c4 = 6) AND (r4c8 = 7) AND (r5c3 = 8) AND (r5c7 = 9) AND (r6c2 = 5) AND (r6c6 = 3) AND (r7c5 = 6) AND (r7c7 = 5) AND (r8c1 = 7) AND (r8c2 = 1) AND (r8c4 = 9) AND (r9c2 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 8) AND (r1c3 = 3) AND (r1c7 = 6) AND (r1c8 = 4) AND (r2c1 = 1) AND (r2c2 = 2) AND (r2c5 = 6) AND (r2c7 = 5) AND (r3c1 = 5) AND (r3c4 = 8) AND (r3c5 = 9) AND (r3c6 = 3) AND (r3c8 = 2) AND (r3c9 = 1) AND (r4c5 = 3) AND (r5c2 = 6) AND (r5c5 = 2) AND (r5c6 = 5) AND (r5c8 = 1) AND (r5c9 = 3) AND (r6c2 = 1) AND (r6c6 = 9) AND (r6c8 = 5) AND (r7c1 = 4) AND (r7c4 = 3) AND (r7c6 = 1) AND (r8c2 = 5) AND (r9c4 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 5) AND (r1c3 = 3) AND (r1c5 = 9) AND (r2c7 = 8) AND (r2c9 = 1) AND (r3c1 = 2) AND (r4c1 = 4) AND (r4c5 = 2) AND (r4c8 = 5) AND (r5c2 = 1) AND (r5c4 = 8) AND (r6c2 = 6) AND (r6c4 = 7) AND (r7c4 = 4) AND (r7c6 = 7) AND (r7c7 = 6) AND (r8c8 = 3) AND (r9c1 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 1) AND (r1c4 = 7) AND (r1c7 = 2) AND (r1c9 = 5) AND (r2c8 = 6) AND (r2c9 = 3) AND (r3c3 = 3) AND (r3c5 = 6) AND (r4c1 = 5) AND (r4c4 = 3) AND (r4c9 = 7) AND (r6c3 = 8) AND (r6c4 = 2) AND (r6c6 = 7) AND (r6c7 = 3) AND (r6c8 = 9) AND (r7c8 = 7) AND (r8c1 = 2) AND (r8c4 = 5) AND (r8c7 = 1) AND (r9c2 = 6) AND (r9c4 = 8) AND (r9c5 = 3) AND (r9c6 = 1) AND (r9c7 = 5) AND (r9c9 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 9) AND (r1c4 = 5) AND (r1c6 = 6) AND (r1c7 = 4) AND (r1c8 = 2) AND (r2c1 = 2) AND (r2c2 = 3) AND (r2c7 = 8) AND (r2c9 = 5) AND (r3c2 = 5) AND (r3c3 = 4) AND (r3c5 = 3) AND (r3c8 = 6) AND (r3c9 = 9) AND (r4c3 = 8) AND (r4c4 = 6) AND (r4c5 = 7) AND (r4c6 = 5) AND (r6c4 = 3) AND (r6c5 = 2) AND (r6c6 = 9) AND (r6c9 = 6) AND (r7c2 = 4) AND (r7c3 = 2) AND (r7c5 = 9) AND (r7c6 = 3) AND (r7c7 = 6) AND (r8c4 = 4) AND (r8c5 = 6) AND (r9c1 = 3) AND (r9c4 = 2) AND (r9c6 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 3) AND (r1c5 = 5) AND (r2c3 = 9) AND (r2c7 = 1) AND (r3c6 = 9) AND (r3c9 = 6) AND (r4c4 = 8) AND (r4c9 = 5) AND (r5c5 = 1) AND (r5c7 = 8) AND (r5c8 = 3) AND (r6c2 = 3) AND (r6c3 = 2) AND (r6c8 = 7) AND (r7c1 = 1) AND (r7c2 = 8) AND (r7c7 = 3) AND (r8c3 = 7) AND (r8c8 = 2) AND (r9c2 = 5) AND (r9c7 = 7) AND (r9c9 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 6) AND (r1c7 = 8) AND (r1c9 = 7) AND (r2c3 = 3) AND (r2c8 = 4) AND (r3c1 = 2) AND (r3c2 = 9) AND (r3c5 = 7) AND (r3c9 = 6) AND (r4c4 = 9) AND (r4c7 = 2) AND (r4c9 = 3) AND (r5c4 = 2) AND (r5c5 = 6) AND (r5c9 = 9) AND (r7c1 = 3) AND (r7c2 = 8) AND (r7c5 = 2) AND (r8c3 = 7) AND (r8c7 = 1) AND (r8c9 = 4) AND (r9c4 = 1) AND (r9c8 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 4) AND (r1c8 = 1) AND (r2c6 = 1) AND (r2c8 = 2) AND (r2c9 = 3) AND (r3c5 = 5) AND (r4c4 = 6) AND (r4c8 = 4) AND (r5c3 = 3) AND (r5c7 = 5) AND (r6c2 = 7) AND (r6c6 = 2) AND (r7c5 = 4) AND (r7c7 = 8) AND (r8c1 = 2) AND (r8c2 = 1) AND (r8c4 = 8) AND (r8c8 = 7) AND (r9c2 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 5) AND (r1c5 = 7) AND (r1c7 = 4) AND (r1c8 = 1) AND (r2c3 = 7) AND (r2c4 = 2) AND (r2c7 = 3) AND (r2c9 = 9) AND (r3c5 = 4) AND (r3c7 = 7) AND (r3c9 = 2) AND (r4c3 = 8) AND (r4c6 = 2) AND (r5c4 = 3) AND (r5c5 = 9) AND (r5c7 = 2) AND (r5c8 = 4) AND (r6c2 = 3) AND (r6c4 = 4) AND (r6c9 = 5) AND (r7c4 = 9) AND (r7c5 = 2) AND (r7c7 = 5) AND (r8c4 = 8) AND (r8c5 = 1) AND (r8c6 = 4) AND (r8c9 = 7) AND (r9c1 = 8) AND (r9c6 = 5);
SELECT * FROM sudoku_memory_combined_view WHERE (r2c2 = 7) AND (r2c4 = 6) AND (r2c5 = 3) AND (r3c3 = 9) AND (r3c4 = 8) AND (r3c8 = 6) AND (r4c7 = 7) AND (r4c8 = 3) AND (r5c3 = 2) AND (r5c4 = 3) AND (r5c7 = 5) AND (r5c9 = 9) AND (r6c3 = 6) AND (r6c5 = 1) AND (r6c7 = 2) AND (r7c1 = 2) AND (r7c3 = 3) AND (r7c6 = 1) AND (r8c1 = 9) AND (r8c5 = 6) AND (r8c9 = 8) AND (r9c2 = 8) AND (r9c3 = 1) AND (r9c4 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 9) AND (r2c4 = 3) AND (r2c5 = 6) AND (r2c7 = 1) AND (r3c5 = 1) AND (r3c6 = 9) AND (r3c7 = 5) AND (r4c1 = 5) AND (r4c8 = 9) AND (r4c9 = 2) AND (r5c5 = 7) AND (r6c4 = 6) AND (r6c9 = 3) AND (r7c4 = 9) AND (r7c7 = 7) AND (r7c8 = 5) AND (r8c5 = 5) AND (r8c6 = 1) AND (r8c8 = 2) AND (r9c2 = 6) AND (r9c5 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 3) AND (r1c3 = 7) AND (r2c1 = 9) AND (r2c2 = 4) AND (r2c3 = 6) AND (r2c9 = 3) AND (r3c1 = 1) AND (r3c4 = 7) AND (r4c1 = 2) AND (r4c2 = 8) AND (r4c3 = 1) AND (r4c4 = 4) AND (r5c3 = 3) AND (r5c6 = 6) AND (r6c1 = 4) AND (r7c5 = 1) AND (r7c7 = 9) AND (r7c9 = 2) AND (r8c3 = 2) AND (r8c4 = 9) AND (r8c6 = 4) AND (r8c9 = 6) AND (r9c1 = 3) AND (r9c2 = 1) AND (r9c5 = 8) AND (r9c8 = 4) AND (r9c9 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r2c1 = 4) AND (r2c2 = 2) AND (r2c3 = 9) AND (r2c5 = 8) AND (r2c6 = 3) AND (r3c2 = 8) AND (r3c4 = 5) AND (r3c6 = 4) AND (r4c5 = 2) AND (r4c7 = 4) AND (r4c8 = 7) AND (r5c2 = 4) AND (r5c4 = 8) AND (r5c6 = 9) AND (r5c8 = 5) AND (r6c3 = 2) AND (r6c4 = 1) AND (r6c7 = 3) AND (r6c9 = 8) AND (r7c2 = 9) AND (r8c1 = 8) AND (r8c5 = 7) AND (r8c6 = 2) AND (r8c9 = 4) AND (r9c4 = 9) AND (r9c5 = 1) AND (r9c6 = 8) AND (r9c9 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 2) AND (r1c7 = 4) AND (r1c9 = 9) AND (r2c2 = 4) AND (r2c8 = 5) AND (r2c9 = 2) AND (r3c3 = 5) AND (r3c7 = 8) AND (r3c8 = 7) AND (r4c2 = 8) AND (r4c8 = 9) AND (r4c9 = 6) AND (r5c3 = 7) AND (r5c6 = 9) AND (r5c7 = 2) AND (r5c8 = 3) AND (r6c3 = 2) AND (r6c5 = 3) AND (r6c7 = 7) AND (r6c9 = 8) AND (r7c2 = 5) AND (r7c5 = 8) AND (r7c7 = 9) AND (r8c1 = 2) AND (r8c3 = 6) AND (r9c3 = 8) AND (r9c4 = 5) AND (r9c6 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 9) AND (r1c5 = 6) AND (r2c3 = 2) AND (r2c7 = 6) AND (r3c2 = 1) AND (r3c6 = 9) AND (r3c7 = 5) AND (r3c9 = 3) AND (r4c2 = 7) AND (r4c7 = 8) AND (r5c1 = 1) AND (r5c8 = 3) AND (r6c3 = 9) AND (r6c9 = 5) AND (r7c2 = 8) AND (r7c6 = 3) AND (r7c9 = 9) AND (r8c1 = 7) AND (r8c3 = 5) AND (r8c6 = 2) AND (r8c7 = 1) AND (r8c9 = 6) AND (r9c1 = 6) AND (r9c8 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c7 = 3) AND (r1c8 = 1) AND (r2c1 = 7) AND (r2c4 = 5) AND (r3c1 = 2) AND (r3c5 = 4) AND (r4c2 = 3) AND (r4c3 = 9) AND (r4c6 = 8) AND (r5c8 = 6) AND (r5c9 = 2) AND (r6c2 = 1) AND (r7c1 = 5) AND (r7c4 = 6) AND (r7c9 = 7) AND (r8c2 = 8) AND (r8c7 = 9) AND (r9c5 = 5);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 5) AND (r1c3 = 1) AND (r1c5 = 7) AND (r1c8 = 6) AND (r1c9 = 3) AND (r2c2 = 6) AND (r2c8 = 2) AND (r3c2 = 2) AND (r3c3 = 3) AND (r3c5 = 6) AND (r3c7 = 7) AND (r3c8 = 9) AND (r5c2 = 1) AND (r5c7 = 3) AND (r5c8 = 5) AND (r6c3 = 9) AND (r6c8 = 4) AND (r7c1 = 6) AND (r7c4 = 4) AND (r7c6 = 9) AND (r7c7 = 5) AND (r8c1 = 5) AND (r8c2 = 9) AND (r8c4 = 6) AND (r8c5 = 3) AND (r8c8 = 7) AND (r8c9 = 4) AND (r9c3 = 4) AND (r9c4 = 7) AND (r9c5 = 5) AND (r9c8 = 3) AND (r9c9 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 7) AND (r1c8 = 9) AND (r2c6 = 2) AND (r2c8 = 3) AND (r2c9 = 4) AND (r3c3 = 2) AND (r3c5 = 5) AND (r4c4 = 4) AND (r4c8 = 2) AND (r5c3 = 6) AND (r5c7 = 7) AND (r6c2 = 5) AND (r6c6 = 3) AND (r7c5 = 6) AND (r7c7 = 5) AND (r8c1 = 8) AND (r8c2 = 1) AND (r8c4 = 9) AND (r9c2 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 1) AND (r1c8 = 8) AND (r2c6 = 1) AND (r2c8 = 2) AND (r2c9 = 3) AND (r3c3 = 4) AND (r3c5 = 5) AND (r4c4 = 2) AND (r4c8 = 6) AND (r5c3 = 7) AND (r5c7 = 8) AND (r6c2 = 5) AND (r6c6 = 9) AND (r7c5 = 7) AND (r7c7 = 5) AND (r8c1 = 6) AND (r8c2 = 3) AND (r8c4 = 8) AND (r9c2 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 2) AND (r1c3 = 7) AND (r1c5 = 3) AND (r1c6 = 4) AND (r1c8 = 6) AND (r1c9 = 5) AND (r2c6 = 8) AND (r2c9 = 2) AND (r3c3 = 4) AND (r3c7 = 7) AND (r4c1 = 4) AND (r4c9 = 3) AND (r5c1 = 8) AND (r5c3 = 2) AND (r5c7 = 6) AND (r5c8 = 4) AND (r6c2 = 7) AND (r6c9 = 8) AND (r7c2 = 2) AND (r7c3 = 1) AND (r7c5 = 8) AND (r7c8 = 5) AND (r8c1 = 6) AND (r8c2 = 4) AND (r8c5 = 2) AND (r8c6 = 5) AND (r8c7 = 3) AND (r9c1 = 5) AND (r9c6 = 7) AND (r9c9 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c8 = 8) AND (r2c1 = 3) AND (r2c4 = 5) AND (r2c6 = 7) AND (r2c7 = 1) AND (r3c6 = 1) AND (r3c8 = 6) AND (r3c9 = 3) AND (r4c3 = 2) AND (r5c1 = 8) AND (r5c3 = 7) AND (r5c7 = 2) AND (r5c8 = 3) AND (r6c1 = 5) AND (r6c5 = 7) AND (r7c2 = 8) AND (r7c5 = 4) AND (r7c6 = 3) AND (r7c8 = 2) AND (r7c9 = 1) AND (r8c1 = 1) AND (r8c3 = 5) AND (r8c9 = 6) AND (r9c1 = 4) AND (r9c2 = 3) AND (r9c7 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 3) AND (r1c8 = 1) AND (r2c6 = 2) AND (r2c8 = 3) AND (r2c9 = 4) AND (r3c3 = 5) AND (r3c5 = 7) AND (r4c4 = 4) AND (r4c8 = 5) AND (r5c3 = 7) AND (r5c7 = 6) AND (r6c2 = 8) AND (r6c6 = 1) AND (r7c5 = 5) AND (r7c7 = 8) AND (r8c1 = 1) AND (r8c2 = 2) AND (r8c4 = 3) AND (r9c2 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c5 = 3) AND (r1c6 = 1) AND (r2c1 = 3) AND (r2c4 = 4) AND (r2c5 = 2) AND (r2c8 = 6) AND (r3c4 = 6) AND (r3c6 = 9) AND (r4c5 = 7) AND (r4c6 = 3) AND (r4c7 = 4) AND (r5c2 = 7) AND (r5c4 = 1) AND (r5c6 = 2) AND (r5c7 = 5) AND (r5c8 = 3) AND (r6c4 = 5) AND (r6c5 = 4) AND (r6c8 = 1) AND (r7c2 = 1) AND (r7c7 = 3) AND (r8c1 = 5) AND (r8c2 = 3) AND (r8c7 = 6) AND (r8c8 = 9) AND (r9c2 = 6) AND (r9c3 = 9) AND (r9c5 = 1) AND (r9c6 = 4) AND (r9c7 = 2) AND (r9c8 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 8) AND (r1c7 = 4) AND (r2c2 = 2) AND (r2c6 = 1) AND (r2c8 = 9) AND (r3c5 = 7) AND (r3c9 = 5) AND (r4c4 = 4) AND (r4c7 = 8) AND (r5c5 = 5) AND (r5c9 = 7) AND (r6c1 = 1) AND (r6c6 = 9) AND (r6c8 = 2) AND (r7c1 = 9) AND (r7c6 = 6) AND (r7c7 = 1) AND (r7c8 = 3) AND (r8c1 = 2) AND (r9c1 = 6) AND (r9c3 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 3) AND (r1c3 = 4) AND (r1c4 = 6) AND (r1c7 = 9) AND (r1c8 = 2) AND (r1c9 = 1) AND (r2c1 = 2) AND (r3c2 = 1) AND (r3c3 = 9) AND (r3c9 = 5) AND (r4c2 = 4) AND (r4c3 = 2) AND (r4c9 = 9) AND (r5c2 = 9) AND (r5c3 = 6) AND (r6c1 = 3) AND (r6c4 = 9) AND (r6c8 = 6) AND (r7c2 = 2) AND (r7c3 = 1) AND (r7c5 = 4) AND (r7c6 = 9) AND (r7c8 = 5) AND (r8c4 = 5) AND (r8c6 = 6) AND (r8c8 = 1) AND (r9c4 = 2) AND (r9c5 = 1) AND (r9c7 = 7) AND (r9c9 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c9 = 4) AND (r2c2 = 3) AND (r2c3 = 1) AND (r2c6 = 9) AND (r2c9 = 7) AND (r3c1 = 2) AND (r3c2 = 9) AND (r3c6 = 1) AND (r4c2 = 7) AND (r4c6 = 6) AND (r5c6 = 2) AND (r5c9 = 9) AND (r6c4 = 7) AND (r6c5 = 4) AND (r7c1 = 5) AND (r7c5 = 1) AND (r7c8 = 2) AND (r8c2 = 6) AND (r8c5 = 9) AND (r8c8 = 7) AND (r8c9 = 3) AND (r9c3 = 3) AND (r9c8 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 4) AND (r1c6 = 2) AND (r1c7 = 5) AND (r1c8 = 6) AND (r2c4 = 7) AND (r2c9 = 3) AND (r3c2 = 1) AND (r4c1 = 6) AND (r4c5 = 9) AND (r4c6 = 8) AND (r5c5 = 1) AND (r6c9 = 4) AND (r7c7 = 1) AND (r7c8 = 8) AND (r8c1 = 4) AND (r8c4 = 3) AND (r9c1 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 7) AND (r1c4 = 4) AND (r1c5 = 2) AND (r1c6 = 6) AND (r1c7 = 1) AND (r2c2 = 4) AND (r2c4 = 3) AND (r2c5 = 7) AND (r2c8 = 2) AND (r3c3 = 6) AND (r3c5 = 1) AND (r3c6 = 5) AND (r3c8 = 7) AND (r4c1 = 6) AND (r5c2 = 8) AND (r5c4 = 5) AND (r6c1 = 4) AND (r6c2 = 5) AND (r6c3 = 2) AND (r6c5 = 6) AND (r6c6 = 3) AND (r7c1 = 5) AND (r7c4 = 7) AND (r7c9 = 2) AND (r8c1 = 7) AND (r8c9 = 1) AND (r9c1 = 3) AND (r9c3 = 4) AND (r9c4 = 6) AND (r9c5 = 5) AND (r9c6 = 2) AND (r9c9 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 9) AND (r1c7 = 3) AND (r1c9 = 6) AND (r2c1 = 7) AND (r2c4 = 6) AND (r2c6 = 4) AND (r2c7 = 8) AND (r3c1 = 6) AND (r3c2 = 1) AND (r3c5 = 3) AND (r3c9 = 7) AND (r4c1 = 1) AND (r4c2 = 6) AND (r4c7 = 4) AND (r4c9 = 3) AND (r5c6 = 1) AND (r5c7 = 7) AND (r6c2 = 8) AND (r6c4 = 4) AND (r6c5 = 9) AND (r6c8 = 1) AND (r7c2 = 9) AND (r7c5 = 4) AND (r8c9 = 4) AND (r9c1 = 2) AND (r9c2 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 4) AND (r1c2 = 3) AND (r1c5 = 7) AND (r1c6 = 6) AND (r1c7 = 5) AND (r1c8 = 9) AND (r2c2 = 6) AND (r2c3 = 5) AND (r2c5 = 4) AND (r3c4 = 5) AND (r3c5 = 9) AND (r3c7 = 3) AND (r4c2 = 1) AND (r4c6 = 8) AND (r4c7 = 4) AND (r4c8 = 5) AND (r5c1 = 3) AND (r5c2 = 7) AND (r5c4 = 6) AND (r5c6 = 4) AND (r5c7 = 1) AND (r5c9 = 9) AND (r6c5 = 1) AND (r6c6 = 9) AND (r6c8 = 7) AND (r6c9 = 3) AND (r7c2 = 9) AND (r7c5 = 8) AND (r8c2 = 5) AND (r8c5 = 6) AND (r8c6 = 7) AND (r8c7 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 8) AND (r1c2 = 4) AND (r1c6 = 6) AND (r1c8 = 2) AND (r2c3 = 6) AND (r2c9 = 9) AND (r3c7 = 1) AND (r4c5 = 9) AND (r4c8 = 3) AND (r5c1 = 3) AND (r5c2 = 6) AND (r5c7 = 9) AND (r6c3 = 2) AND (r6c4 = 8) AND (r7c2 = 9) AND (r7c7 = 4) AND (r7c8 = 7) AND (r8c2 = 7) AND (r8c3 = 1) AND (r8c5 = 4) AND (r8c7 = 6) AND (r8c9 = 8) AND (r9c1 = 2) AND (r9c9 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 2) AND (r1c4 = 3) AND (r1c6 = 8) AND (r1c8 = 6) AND (r2c1 = 8) AND (r2c5 = 7) AND (r2c9 = 2) AND (r3c3 = 6) AND (r3c4 = 5) AND (r3c6 = 2) AND (r3c7 = 8) AND (r4c1 = 6) AND (r4c3 = 2) AND (r4c7 = 7) AND (r4c9 = 3) AND (r5c2 = 9) AND (r5c8 = 2) AND (r6c1 = 3) AND (r6c3 = 5) AND (r6c7 = 9) AND (r6c9 = 4) AND (r7c3 = 7) AND (r7c4 = 2) AND (r7c6 = 1) AND (r7c7 = 6) AND (r8c1 = 5) AND (r8c5 = 6) AND (r8c9 = 1) AND (r9c2 = 6) AND (r9c4 = 4) AND (r9c6 = 5) AND (r9c8 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 2) AND (r1c3 = 4) AND (r1c8 = 3) AND (r1c9 = 1) AND (r2c1 = 9) AND (r2c3 = 6) AND (r2c4 = 4) AND (r2c5 = 5) AND (r3c3 = 3) AND (r3c5 = 7) AND (r3c8 = 6) AND (r5c1 = 4) AND (r5c8 = 7) AND (r5c9 = 9) AND (r6c4 = 5) AND (r6c5 = 6) AND (r7c1 = 1) AND (r7c4 = 2) AND (r8c1 = 6) AND (r8c2 = 7) AND (r8c5 = 4) AND (r9c5 = 9) AND (r9c6 = 7) AND (r9c8 = 5);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 6) AND (r1c7 = 4) AND (r2c1 = 9) AND (r2c3 = 3) AND (r3c4 = 4) AND (r3c8 = 2) AND (r4c9 = 9) AND (r5c1 = 2) AND (r5c7 = 3) AND (r6c5 = 3) AND (r6c6 = 1) AND (r6c7 = 7) AND (r7c1 = 5) AND (r7c2 = 9) AND (r7c3 = 7) AND (r8c1 = 4) AND (r8c4 = 9) AND (r9c2 = 2) AND (r9c7 = 6) AND (r9c9 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 5) AND (r1c4 = 7) AND (r1c8 = 3) AND (r2c2 = 8) AND (r2c6 = 9) AND (r2c9 = 5) AND (r3c4 = 1) AND (r3c7 = 6) AND (r3c9 = 2) AND (r4c8 = 9) AND (r5c5 = 6) AND (r6c4 = 3) AND (r6c6 = 1) AND (r7c2 = 7) AND (r7c8 = 8) AND (r8c1 = 6) AND (r8c4 = 2) AND (r8c5 = 8) AND (r8c7 = 3) AND (r9c1 = 1) AND (r9c2 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c7 = 7) AND (r2c2 = 4) AND (r2c7 = 1) AND (r2c9 = 3) AND (r3c6 = 9) AND (r3c8 = 6) AND (r3c9 = 5) AND (r4c3 = 4) AND (r5c2 = 3) AND (r5c3 = 7) AND (r5c4 = 2) AND (r5c8 = 9) AND (r6c4 = 1) AND (r7c1 = 7) AND (r7c5 = 1) AND (r7c7 = 6) AND (r8c3 = 5) AND (r8c6 = 7) AND (r8c7 = 2) AND (r9c5 = 6) AND (r9c6 = 5) AND (r9c8 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 2) AND (r1c5 = 3) AND (r1c8 = 5) AND (r2c2 = 8) AND (r2c9 = 1) AND (r3c2 = 9) AND (r4c1 = 5) AND (r4c6 = 1) AND (r4c8 = 3) AND (r5c5 = 8) AND (r5c7 = 9) AND (r6c1 = 2) AND (r7c2 = 4) AND (r7c4 = 6) AND (r7c7 = 8) AND (r8c1 = 7) AND (r8c4 = 5);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 6) AND (r1c5 = 4) AND (r1c6 = 1) AND (r1c7 = 8) AND (r1c9 = 5) AND (r2c3 = 8) AND (r2c6 = 2) AND (r2c7 = 4) AND (r2c9 = 1) AND (r3c1 = 1) AND (r3c3 = 4) AND (r3c4 = 5) AND (r3c5 = 8) AND (r3c8 = 6) AND (r4c3 = 1) AND (r4c5 = 3) AND (r4c9 = 4) AND (r6c6 = 9) AND (r6c9 = 3) AND (r7c2 = 2) AND (r7c3 = 6) AND (r8c1 = 5) AND (r8c3 = 9) AND (r8c5 = 1) AND (r8c6 = 4) AND (r8c8 = 2) AND (r8c9 = 6) AND (r9c1 = 4) AND (r9c5 = 6) AND (r9c9 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 3) AND (r1c4 = 2) AND (r2c1 = 5) AND (r2c5 = 8) AND (r2c7 = 6) AND (r2c9 = 4) AND (r3c9 = 9) AND (r4c1 = 3) AND (r4c4 = 4) AND (r4c5 = 5) AND (r5c3 = 8) AND (r5c4 = 1) AND (r5c5 = 9) AND (r5c6 = 6) AND (r6c1 = 4) AND (r6c5 = 3) AND (r6c7 = 1) AND (r6c9 = 6) AND (r7c1 = 1) AND (r7c4 = 6) AND (r7c7 = 9) AND (r7c8 = 5) AND (r7c9 = 8) AND (r8c4 = 5) AND (r9c1 = 8) AND (r9c2 = 6) AND (r9c7 = 4) AND (r9c9 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 6) AND (r1c3 = 4) AND (r1c4 = 3) AND (r1c5 = 1) AND (r1c9 = 5) AND (r2c2 = 2) AND (r2c5 = 5) AND (r2c7 = 6) AND (r2c9 = 4) AND (r3c3 = 8) AND (r3c5 = 6) AND (r3c6 = 4) AND (r3c8 = 2) AND (r4c3 = 1) AND (r4c7 = 9) AND (r4c9 = 2) AND (r5c2 = 3) AND (r6c1 = 8) AND (r6c5 = 2) AND (r6c6 = 6) AND (r6c9 = 1) AND (r7c4 = 5) AND (r7c5 = 9) AND (r8c1 = 3) AND (r8c6 = 8) AND (r9c1 = 9) AND (r9c5 = 4) AND (r9c6 = 3) AND (r9c8 = 5);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c6 = 1) AND (r1c8 = 7) AND (r1c9 = 3) AND (r2c4 = 5) AND (r2c5 = 6) AND (r2c7 = 8) AND (r2c8 = 4) AND (r3c4 = 3) AND (r3c6 = 8) AND (r3c7 = 6) AND (r4c5 = 5) AND (r4c6 = 2) AND (r4c7 = 7) AND (r4c9 = 6) AND (r5c4 = 7) AND (r5c5 = 1) AND (r5c8 = 3) AND (r7c1 = 2) AND (r7c2 = 7) AND (r7c8 = 6) AND (r7c9 = 8) AND (r8c2 = 4) AND (r8c3 = 5) AND (r8c4 = 1) AND (r9c1 = 6) AND (r9c2 = 8) AND (r9c3 = 3) AND (r9c6 = 7) AND (r9c9 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c5 = 5) AND (r1c8 = 1) AND (r2c1 = 5) AND (r2c2 = 8) AND (r3c5 = 7) AND (r4c4 = 7) AND (r4c5 = 2) AND (r4c6 = 4) AND (r4c7 = 1) AND (r4c8 = 8) AND (r5c1 = 1) AND (r5c5 = 8) AND (r5c9 = 9) AND (r6c2 = 7) AND (r6c4 = 1) AND (r6c5 = 3) AND (r6c8 = 4) AND (r7c1 = 3) AND (r7c3 = 2) AND (r7c5 = 9) AND (r7c7 = 8) AND (r7c8 = 5) AND (r7c9 = 4) AND (r8c2 = 9) AND (r8c3 = 7) AND (r8c7 = 2) AND (r9c1 = 8) AND (r9c3 = 5) AND (r9c6 = 2) AND (r9c8 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 4) AND (r1c6 = 7) AND (r1c9 = 2) AND (r2c1 = 5) AND (r2c2 = 2) AND (r2c4 = 9) AND (r2c5 = 3) AND (r2c7 = 4) AND (r3c4 = 5) AND (r3c9 = 7) AND (r4c1 = 9) AND (r4c2 = 3) AND (r4c9 = 4) AND (r5c9 = 1) AND (r6c6 = 1) AND (r6c7 = 3) AND (r7c3 = 4) AND (r7c5 = 2) AND (r8c1 = 2) AND (r8c2 = 9) AND (r8c5 = 7) AND (r9c1 = 1) AND (r9c5 = 8) AND (r9c6 = 5) AND (r9c8 = 2) AND (r9c9 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 4) AND (r1c7 = 7) AND (r1c8 = 5) AND (r1c9 = 3) AND (r2c2 = 7) AND (r2c3 = 9) AND (r2c6 = 3) AND (r2c7 = 2) AND (r2c8 = 1) AND (r3c3 = 5) AND (r4c5 = 2) AND (r5c3 = 4) AND (r5c5 = 3) AND (r5c7 = 1) AND (r5c9 = 7) AND (r6c1 = 3) AND (r6c3 = 6) AND (r6c4 = 1) AND (r6c7 = 4) AND (r6c8 = 2) AND (r7c1 = 2) AND (r7c3 = 3) AND (r7c6 = 6) AND (r7c7 = 5) AND (r7c9 = 1) AND (r8c2 = 6) AND (r8c3 = 7) AND (r8c5 = 1) AND (r8c8 = 4) AND (r8c9 = 2) AND (r9c7 = 6) AND (r9c8 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 3) AND (r1c3 = 7) AND (r1c8 = 5) AND (r2c3 = 9) AND (r2c5 = 6) AND (r2c8 = 1) AND (r3c6 = 1) AND (r3c7 = 3) AND (r4c2 = 7) AND (r5c3 = 1) AND (r5c4 = 2) AND (r5c6 = 7) AND (r5c9 = 5) AND (r6c5 = 3) AND (r6c7 = 8) AND (r6c9 = 6) AND (r7c6 = 3) AND (r8c4 = 7) AND (r8c5 = 8) AND (r9c1 = 6) AND (r9c8 = 9) AND (r9c9 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 3) AND (r1c7 = 5) AND (r1c8 = 9) AND (r2c2 = 5) AND (r2c3 = 1) AND (r2c5 = 6) AND (r2c6 = 3) AND (r3c3 = 9) AND (r3c5 = 2) AND (r5c2 = 7) AND (r5c3 = 3) AND (r5c5 = 5) AND (r5c8 = 2) AND (r6c3 = 2) AND (r6c7 = 1) AND (r6c8 = 7) AND (r7c2 = 9) AND (r7c4 = 7) AND (r7c6 = 6) AND (r7c7 = 3) AND (r7c8 = 5) AND (r8c1 = 7) AND (r8c2 = 8) AND (r9c5 = 8) AND (r9c9 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r2c4 = 4) AND (r2c8 = 5) AND (r3c1 = 8) AND (r3c2 = 5) AND (r3c3 = 9) AND (r3c4 = 2) AND (r4c3 = 3) AND (r4c4 = 5) AND (r4c7 = 4) AND (r4c8 = 9) AND (r5c7 = 5) AND (r5c9 = 6) AND (r6c3 = 7) AND (r6c4 = 9) AND (r6c5 = 2) AND (r6c6 = 4) AND (r6c8 = 3) AND (r6c9 = 8) AND (r7c6 = 2) AND (r7c8 = 8) AND (r8c1 = 7) AND (r8c4 = 8) AND (r8c5 = 5) AND (r8c7 = 9) AND (r8c8 = 4) AND (r9c2 = 3) AND (r9c4 = 7) AND (r9c5 = 4) AND (r9c8 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 9) AND (r1c7 = 6) AND (r2c1 = 8) AND (r2c3 = 6) AND (r2c4 = 7) AND (r2c5 = 4) AND (r2c6 = 5) AND (r2c8 = 2) AND (r2c9 = 9) AND (r3c3 = 4) AND (r3c6 = 3) AND (r3c8 = 7) AND (r3c9 = 5) AND (r4c1 = 4) AND (r4c4 = 3) AND (r4c5 = 7) AND (r4c6 = 9) AND (r4c8 = 6) AND (r5c6 = 4) AND (r6c1 = 7) AND (r6c5 = 8) AND (r6c8 = 5) AND (r7c3 = 8) AND (r7c4 = 4) AND (r7c6 = 6) AND (r8c1 = 3) AND (r8c5 = 5) AND (r8c6 = 8) AND (r9c4 = 2) AND (r9c5 = 3) AND (r9c9 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c5 = 7) AND (r3c3 = 3) AND (r3c5 = 2) AND (r3c8 = 5) AND (r4c2 = 6) AND (r4c5 = 4) AND (r4c9 = 2) AND (r5c3 = 8) AND (r5c4 = 5) AND (r5c6 = 9) AND (r6c4 = 6) AND (r7c1 = 6) AND (r7c8 = 9) AND (r8c3 = 2) AND (r8c5 = 3) AND (r8c9 = 4) AND (r9c1 = 4) AND (r9c2 = 7) AND (r9c4 = 8) AND (r9c7 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 3) AND (r1c4 = 4) AND (r1c6 = 6) AND (r2c2 = 9) AND (r2c7 = 7) AND (r4c1 = 6) AND (r4c3 = 4) AND (r4c4 = 1) AND (r5c5 = 7) AND (r5c7 = 2) AND (r5c9 = 9) AND (r6c7 = 5) AND (r7c5 = 3) AND (r7c8 = 8) AND (r8c1 = 5) AND (r8c2 = 2) AND (r9c4 = 8) AND (r9c8 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 7) AND (r1c5 = 2) AND (r2c2 = 8) AND (r2c6 = 6) AND (r3c6 = 3) AND (r3c9 = 6) AND (r4c3 = 3) AND (r4c5 = 4) AND (r4c7 = 7) AND (r4c8 = 8) AND (r5c1 = 2) AND (r5c5 = 1) AND (r6c2 = 6) AND (r6c9 = 5) AND (r7c4 = 1) AND (r7c7 = 3) AND (r7c8 = 7) AND (r8c5 = 5) AND (r9c3 = 8) AND (r9c6 = 7) AND (r9c8 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c8 = 8) AND (r2c1 = 3) AND (r2c2 = 5) AND (r2c3 = 1) AND (r2c5 = 7) AND (r3c6 = 9) AND (r3c7 = 7) AND (r3c9 = 3) AND (r4c3 = 7) AND (r4c4 = 1) AND (r4c6 = 8) AND (r4c7 = 5) AND (r5c5 = 3) AND (r5c7 = 2) AND (r6c2 = 8) AND (r6c6 = 5) AND (r6c8 = 9) AND (r7c7 = 1) AND (r7c8 = 5) AND (r7c9 = 2) AND (r8c3 = 3) AND (r8c4 = 4) AND (r8c6 = 1) AND (r9c4 = 9) AND (r9c5 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c7 = 3) AND (r1c9 = 8) AND (r2c1 = 7) AND (r2c2 = 2) AND (r2c4 = 9) AND (r2c9 = 6) AND (r3c4 = 1) AND (r4c2 = 8) AND (r4c6 = 6) AND (r5c3 = 7) AND (r5c5 = 5) AND (r5c8 = 6) AND (r6c1 = 3) AND (r6c5 = 2) AND (r7c1 = 5) AND (r7c3 = 8) AND (r7c4 = 7) AND (r7c5 = 1) AND (r8c6 = 9) AND (r9c1 = 2) AND (r9c3 = 6) AND (r9c9 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 5) AND (r1c3 = 2) AND (r1c4 = 9) AND (r2c7 = 8) AND (r3c8 = 4) AND (r3c9 = 6) AND (r4c2 = 1) AND (r4c6 = 2) AND (r4c9 = 3) AND (r5c1 = 3) AND (r5c2 = 7) AND (r6c6 = 4) AND (r7c8 = 7) AND (r8c1 = 6) AND (r8c4 = 5) AND (r8c6 = 1) AND (r9c1 = 4) AND (r9c4 = 3) AND (r9c6 = 9) AND (r9c7 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 7) AND (r1c5 = 6) AND (r1c6 = 4) AND (r1c8 = 2) AND (r1c9 = 5) AND (r2c2 = 5) AND (r2c6 = 9) AND (r2c9 = 1) AND (r3c5 = 2) AND (r3c8 = 4) AND (r3c9 = 9) AND (r4c1 = 5) AND (r4c3 = 6) AND (r4c6 = 3) AND (r4c8 = 1) AND (r5c1 = 4) AND (r5c3 = 2) AND (r6c2 = 1) AND (r7c1 = 3) AND (r7c2 = 6) AND (r7c3 = 9) AND (r7c4 = 4) AND (r7c8 = 5) AND (r8c3 = 5) AND (r8c6 = 6) AND (r9c1 = 7) AND (r9c9 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 9) AND (r1c5 = 6) AND (r1c6 = 5) AND (r1c9 = 7) AND (r2c1 = 5) AND (r2c6 = 3) AND (r2c8 = 6) AND (r2c9 = 8) AND (r3c3 = 8) AND (r3c4 = 4) AND (r3c9 = 9) AND (r4c3 = 2) AND (r5c5 = 5) AND (r5c9 = 3) AND (r6c3 = 6) AND (r6c6 = 7) AND (r7c5 = 9) AND (r7c7 = 2) AND (r8c4 = 3) AND (r8c7 = 4) AND (r9c1 = 6) AND (r9c8 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 7) AND (r1c4 = 3) AND (r1c8 = 6) AND (r2c5 = 8) AND (r2c7 = 5) AND (r3c2 = 1) AND (r4c1 = 8) AND (r4c3 = 9) AND (r4c4 = 6) AND (r4c7 = 4) AND (r5c4 = 1) AND (r5c6 = 2) AND (r6c1 = 5) AND (r7c4 = 7) AND (r7c8 = 3) AND (r7c9 = 2) AND (r8c1 = 4) AND (r8c5 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c6 = 4) AND (r1c8 = 6) AND (r2c4 = 1) AND (r2c5 = 2) AND (r2c6 = 9) AND (r2c8 = 8) AND (r2c9 = 4) AND (r3c3 = 2) AND (r4c3 = 5) AND (r4c7 = 4) AND (r5c2 = 2) AND (r5c4 = 4) AND (r5c5 = 1) AND (r5c7 = 8) AND (r5c8 = 5) AND (r6c2 = 6) AND (r6c4 = 5) AND (r6c6 = 8) AND (r6c8 = 2) AND (r7c1 = 2) AND (r7c2 = 1) AND (r7c3 = 6) AND (r7c6 = 5) AND (r8c2 = 8) AND (r8c4 = 2) AND (r8c5 = 3) AND (r9c2 = 3) AND (r9c3 = 4) AND (r9c4 = 8) AND (r9c6 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 8) AND (r1c7 = 1) AND (r1c9 = 4) AND (r2c1 = 7) AND (r2c2 = 3) AND (r4c5 = 7) AND (r4c6 = 2) AND (r4c7 = 6) AND (r5c2 = 1) AND (r5c3 = 3) AND (r7c3 = 4) AND (r7c4 = 3) AND (r7c5 = 1) AND (r8c1 = 2) AND (r8c7 = 5) AND (r8c8 = 7) AND (r9c8 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 9) AND (r1c5 = 4) AND (r1c8 = 8) AND (r2c2 = 4) AND (r2c9 = 7) AND (r3c4 = 6) AND (r3c9 = 2) AND (r4c3 = 5) AND (r4c7 = 7) AND (r4c8 = 4) AND (r5c1 = 9) AND (r5c2 = 6) AND (r5c7 = 5) AND (r6c4 = 2) AND (r7c2 = 5) AND (r7c5 = 2) AND (r7c9 = 8) AND (r8c3 = 4) AND (r8c5 = 8) AND (r8c6 = 3) AND (r9c2 = 8) AND (r9c4 = 9) AND (r9c5 = 7) AND (r9c8 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 2) AND (r1c5 = 6) AND (r1c8 = 8) AND (r2c1 = 9) AND (r2c3 = 4) AND (r4c2 = 8) AND (r4c4 = 5) AND (r4c8 = 6) AND (r5c1 = 7) AND (r5c6 = 9) AND (r6c9 = 1) AND (r7c2 = 2) AND (r7c4 = 6) AND (r8c5 = 3) AND (r8c7 = 9) AND (r9c1 = 1) AND (r9c7 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 4) AND (r1c3 = 8) AND (r1c4 = 9) AND (r1c6 = 7) AND (r1c7 = 1) AND (r3c4 = 4) AND (r3c5 = 3) AND (r3c6 = 1) AND (r4c6 = 4) AND (r5c5 = 9) AND (r5c7 = 7) AND (r6c1 = 6) AND (r6c5 = 2) AND (r6c6 = 3) AND (r7c2 = 7) AND (r7c6 = 8) AND (r7c7 = 3) AND (r7c9 = 9) AND (r8c1 = 1) AND (r8c3 = 3) AND (r8c5 = 7) AND (r8c6 = 2) AND (r8c7 = 8) AND (r8c9 = 4) AND (r9c2 = 8) AND (r9c3 = 4) AND (r9c7 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 7) AND (r1c3 = 5) AND (r1c7 = 8) AND (r1c8 = 2) AND (r2c1 = 2) AND (r2c2 = 9) AND (r2c3 = 8) AND (r2c4 = 7) AND (r3c1 = 4) AND (r3c2 = 3) AND (r3c8 = 5) AND (r3c9 = 9) AND (r4c1 = 8) AND (r4c4 = 3) AND (r4c5 = 4) AND (r4c6 = 6) AND (r5c4 = 2) AND (r5c7 = 3) AND (r6c5 = 5) AND (r6c6 = 7) AND (r7c5 = 6) AND (r7c6 = 4) AND (r8c4 = 8) AND (r8c6 = 9) AND (r8c8 = 4) AND (r9c4 = 5) AND (r9c5 = 3) AND (r9c7 = 6) AND (r9c8 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 1) AND (r1c8 = 8) AND (r2c8 = 6) AND (r3c3 = 8) AND (r3c4 = 4) AND (r3c7 = 1) AND (r4c1 = 5) AND (r4c3 = 6) AND (r4c7 = 4) AND (r5c5 = 9) AND (r5c8 = 5) AND (r5c9 = 7) AND (r6c5 = 8) AND (r6c6 = 4) AND (r7c4 = 8) AND (r7c6 = 7) AND (r7c7 = 2) AND (r8c2 = 2) AND (r8c3 = 7) AND (r8c5 = 1) AND (r9c2 = 5) AND (r9c4 = 6) AND (r9c6 = 2) AND (r9c7 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 6) AND (r1c4 = 3) AND (r1c6 = 1) AND (r2c5 = 8) AND (r2c9 = 1) AND (r3c2 = 8) AND (r3c4 = 9) AND (r3c5 = 5) AND (r3c6 = 7) AND (r3c8 = 3) AND (r4c1 = 9) AND (r4c3 = 8) AND (r4c5 = 3) AND (r4c6 = 4) AND (r4c8 = 6) AND (r5c6 = 9) AND (r6c4 = 1) AND (r6c5 = 7) AND (r6c6 = 8) AND (r6c8 = 9) AND (r6c9 = 5) AND (r7c1 = 8) AND (r7c2 = 6) AND (r7c6 = 5) AND (r7c7 = 7) AND (r7c8 = 1) AND (r8c1 = 7) AND (r8c3 = 1) AND (r8c6 = 3) AND (r8c7 = 5) AND (r8c9 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c8 = 4) AND (r2c1 = 6) AND (r2c4 = 3) AND (r2c5 = 8) AND (r2c9 = 7) AND (r3c4 = 7) AND (r3c5 = 9) AND (r3c6 = 6) AND (r4c4 = 6) AND (r4c8 = 3) AND (r5c5 = 1) AND (r6c3 = 7) AND (r6c4 = 4) AND (r6c9 = 2) AND (r7c2 = 4) AND (r7c4 = 8) AND (r7c9 = 6) AND (r8c1 = 3) AND (r8c2 = 1) AND (r9c2 = 9) AND (r9c7 = 2) AND (r9c8 = 1) AND (r9c9 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 1) AND (r1c7 = 6) AND (r2c2 = 4) AND (r2c3 = 3) AND (r2c8 = 8) AND (r2c9 = 5) AND (r3c1 = 6) AND (r3c4 = 5) AND (r3c9 = 2) AND (r4c6 = 3) AND (r4c7 = 2) AND (r5c3 = 5) AND (r5c5 = 1) AND (r5c6 = 7) AND (r5c8 = 6) AND (r5c9 = 8) AND (r6c4 = 8) AND (r6c6 = 5) AND (r6c9 = 1) AND (r7c3 = 2) AND (r7c6 = 6) AND (r7c7 = 1) AND (r7c8 = 3) AND (r7c9 = 4) AND (r8c1 = 4) AND (r8c6 = 1) AND (r8c8 = 2) AND (r8c9 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 4) AND (r1c5 = 2) AND (r1c6 = 9) AND (r1c7 = 3) AND (r1c8 = 6) AND (r2c1 = 3) AND (r2c2 = 8) AND (r2c4 = 1) AND (r2c5 = 4) AND (r2c8 = 2) AND (r3c2 = 9) AND (r4c2 = 1) AND (r4c3 = 9) AND (r4c4 = 8) AND (r4c7 = 4) AND (r5c4 = 4) AND (r5c5 = 9) AND (r5c9 = 7) AND (r6c6 = 3) AND (r7c1 = 8) AND (r7c3 = 6) AND (r8c3 = 7) AND (r8c7 = 8) AND (r9c6 = 2) AND (r9c8 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 1) AND (r1c8 = 6) AND (r2c1 = 6) AND (r2c5 = 7) AND (r2c6 = 2) AND (r3c9 = 9) AND (r4c1 = 1) AND (r4c2 = 8) AND (r4c4 = 2) AND (r4c7 = 5) AND (r6c6 = 5) AND (r6c8 = 9) AND (r6c9 = 4) AND (r7c1 = 7) AND (r7c2 = 5) AND (r7c7 = 9) AND (r8c1 = 4) AND (r8c6 = 6) AND (r8c7 = 8) AND (r8c8 = 5) AND (r9c3 = 6) AND (r9c5 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 6) AND (r1c6 = 7) AND (r1c7 = 5) AND (r2c5 = 5) AND (r2c8 = 6) AND (r2c9 = 4) AND (r3c2 = 5) AND (r3c5 = 6) AND (r3c7 = 9) AND (r3c8 = 8) AND (r3c9 = 1) AND (r4c1 = 1) AND (r5c3 = 7) AND (r5c4 = 9) AND (r5c9 = 2) AND (r6c2 = 9) AND (r6c7 = 1) AND (r7c3 = 4) AND (r7c5 = 1) AND (r7c6 = 5) AND (r7c9 = 9) AND (r8c1 = 8) AND (r8c5 = 7) AND (r8c9 = 6) AND (r9c6 = 2) AND (r9c8 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 9) AND (r1c5 = 6) AND (r2c2 = 2) AND (r2c3 = 7) AND (r2c5 = 9) AND (r2c6 = 1) AND (r2c9 = 5) AND (r3c3 = 3) AND (r3c4 = 7) AND (r3c6 = 8) AND (r4c8 = 3) AND (r5c1 = 5) AND (r5c3 = 6) AND (r5c5 = 2) AND (r5c6 = 9) AND (r5c7 = 7) AND (r6c1 = 2) AND (r6c3 = 1) AND (r6c6 = 7) AND (r7c1 = 3) AND (r7c3 = 9) AND (r7c6 = 6) AND (r7c7 = 1) AND (r7c8 = 2) AND (r8c2 = 6) AND (r8c3 = 5) AND (r8c5 = 1) AND (r8c6 = 2) AND (r9c1 = 1) AND (r9c4 = 9) AND (r9c5 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 3) AND (r1c7 = 7) AND (r1c8 = 6) AND (r2c1 = 8) AND (r2c5 = 2) AND (r2c6 = 6) AND (r2c8 = 5) AND (r3c1 = 4) AND (r3c2 = 5) AND (r4c8 = 1) AND (r5c3 = 2) AND (r5c4 = 8) AND (r5c6 = 5) AND (r5c8 = 3) AND (r5c9 = 7) AND (r6c9 = 8) AND (r7c1 = 2) AND (r7c3 = 8) AND (r7c4 = 6) AND (r8c2 = 3) AND (r8c4 = 5) AND (r8c7 = 6) AND (r8c8 = 2) AND (r9c3 = 7) AND (r9c6 = 2) AND (r9c9 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 9) AND (r2c2 = 1) AND (r2c5 = 8) AND (r2c6 = 6) AND (r2c7 = 4) AND (r3c2 = 4) AND (r4c3 = 8) AND (r4c7 = 1) AND (r4c8 = 3) AND (r5c1 = 5) AND (r5c2 = 3) AND (r6c2 = 7) AND (r6c3 = 1) AND (r6c5 = 3) AND (r6c7 = 5) AND (r7c3 = 7) AND (r7c4 = 4) AND (r7c8 = 1) AND (r8c2 = 5) AND (r8c3 = 4) AND (r8c4 = 7) AND (r8c5 = 9) AND (r8c7 = 6) AND (r8c9 = 8) AND (r9c2 = 6) AND (r9c3 = 9) AND (r9c4 = 8) AND (r9c5 = 5) AND (r9c6 = 1) AND (r9c7 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 7) AND (r1c3 = 8) AND (r1c5 = 2) AND (r2c8 = 9) AND (r2c9 = 1) AND (r3c1 = 3) AND (r4c2 = 4) AND (r4c3 = 6) AND (r5c5 = 3) AND (r5c7 = 7) AND (r6c4 = 5) AND (r7c2 = 5) AND (r7c4 = 9) AND (r7c6 = 6) AND (r8c4 = 4) AND (r8c8 = 1) AND (r9c1 = 2) AND (r9c7 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c7 = 3) AND (r1c9 = 2) AND (r2c3 = 8) AND (r3c5 = 5) AND (r4c9 = 4) AND (r5c2 = 5) AND (r5c5 = 7) AND (r5c8 = 2) AND (r6c2 = 7) AND (r6c4 = 3) AND (r6c5 = 8) AND (r6c6 = 4) AND (r6c8 = 5) AND (r7c2 = 9) AND (r7c3 = 7) AND (r7c6 = 8) AND (r7c9 = 5) AND (r8c2 = 8) AND (r8c3 = 2) AND (r8c5 = 1) AND (r8c6 = 7) AND (r8c8 = 4) AND (r9c2 = 1) AND (r9c3 = 5) AND (r9c4 = 4) AND (r9c5 = 2) AND (r9c9 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 7) AND (r1c6 = 5) AND (r2c1 = 6) AND (r2c9 = 4) AND (r3c1 = 8) AND (r3c2 = 5) AND (r3c6 = 7) AND (r4c6 = 8) AND (r4c9 = 6) AND (r5c1 = 9) AND (r5c2 = 6) AND (r5c5 = 4) AND (r5c7 = 5) AND (r6c3 = 1) AND (r6c6 = 3) AND (r6c7 = 8) AND (r7c3 = 4) AND (r7c5 = 7) AND (r8c1 = 3) AND (r8c4 = 8) AND (r8c7 = 9) AND (r8c9 = 7) AND (r9c2 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 8) AND (r1c5 = 7) AND (r1c8 = 2) AND (r2c7 = 6) AND (r2c9 = 4) AND (r3c3 = 6) AND (r3c4 = 9) AND (r3c6 = 5) AND (r3c7 = 3) AND (r4c4 = 5) AND (r4c6 = 7) AND (r5c5 = 9) AND (r5c8 = 8) AND (r5c9 = 2) AND (r6c7 = 5) AND (r7c1 = 2) AND (r7c2 = 3) AND (r7c6 = 4) AND (r7c9 = 9) AND (r8c1 = 4) AND (r8c4 = 7) AND (r8c5 = 6) AND (r8c9 = 5) AND (r9c1 = 5) AND (r9c5 = 3) AND (r9c6 = 9) AND (r9c8 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 6) AND (r1c4 = 8) AND (r1c6 = 9) AND (r1c9 = 5) AND (r2c1 = 5) AND (r2c6 = 4) AND (r3c1 = 9) AND (r3c2 = 2) AND (r3c7 = 6) AND (r4c3 = 1) AND (r4c7 = 3) AND (r5c3 = 3) AND (r5c5 = 8) AND (r5c9 = 6) AND (r6c1 = 6) AND (r6c4 = 1) AND (r6c5 = 9) AND (r6c8 = 5) AND (r6c9 = 8) AND (r7c9 = 3) AND (r8c6 = 2) AND (r9c4 = 6) AND (r9c7 = 1) AND (r9c9 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c7 = 6) AND (r1c9 = 7) AND (r2c4 = 7) AND (r2c5 = 9) AND (r2c8 = 8) AND (r2c9 = 3) AND (r3c5 = 8) AND (r3c7 = 5) AND (r3c8 = 4) AND (r4c2 = 4) AND (r4c3 = 3) AND (r4c5 = 1) AND (r4c9 = 5) AND (r5c3 = 5) AND (r5c8 = 6) AND (r6c2 = 6) AND (r6c5 = 3) AND (r6c7 = 4) AND (r7c1 = 6) AND (r7c4 = 3) AND (r7c6 = 9) AND (r7c7 = 8) AND (r8c6 = 5) AND (r8c8 = 9) AND (r9c1 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c6 = 2) AND (r2c2 = 4) AND (r2c6 = 6) AND (r2c8 = 7) AND (r2c9 = 1) AND (r3c3 = 9) AND (r3c4 = 3) AND (r3c7 = 4) AND (r4c4 = 9) AND (r4c5 = 4) AND (r5c3 = 6) AND (r5c6 = 1) AND (r5c9 = 7) AND (r6c3 = 1) AND (r6c5 = 2) AND (r6c6 = 7) AND (r7c1 = 7) AND (r7c3 = 4) AND (r7c4 = 1) AND (r7c5 = 6) AND (r7c8 = 9) AND (r7c9 = 5) AND (r8c1 = 9) AND (r9c1 = 6) AND (r9c2 = 1) AND (r9c5 = 5) AND (r9c8 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 7) AND (r1c6 = 1) AND (r1c8 = 4) AND (r2c1 = 8) AND (r2c3 = 9) AND (r2c4 = 2) AND (r2c8 = 1) AND (r3c4 = 8) AND (r3c6 = 7) AND (r3c7 = 2) AND (r3c9 = 5) AND (r4c1 = 5) AND (r5c3 = 4) AND (r5c4 = 6) AND (r5c8 = 8) AND (r6c3 = 7) AND (r6c4 = 4) AND (r7c4 = 9) AND (r7c8 = 6) AND (r7c9 = 8) AND (r8c1 = 9) AND (r8c3 = 5) AND (r8c4 = 1) AND (r8c6 = 8) AND (r8c7 = 4) AND (r8c8 = 7) AND (r9c1 = 4) AND (r9c3 = 8) AND (r9c5 = 2) AND (r9c8 = 5) AND (r9c9 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 7) AND (r1c3 = 8) AND (r1c9 = 4) AND (r2c1 = 6) AND (r2c3 = 2) AND (r2c7 = 5) AND (r2c8 = 8) AND (r3c1 = 5) AND (r3c2 = 4) AND (r3c5 = 2) AND (r3c7 = 1) AND (r3c8 = 6) AND (r3c9 = 7) AND (r4c7 = 8) AND (r4c8 = 4) AND (r5c1 = 2) AND (r5c7 = 7) AND (r5c9 = 5) AND (r6c1 = 4) AND (r6c2 = 8) AND (r6c3 = 5) AND (r6c6 = 1) AND (r6c8 = 2) AND (r7c1 = 7) AND (r7c4 = 3) AND (r7c6 = 4) AND (r8c9 = 2) AND (r9c1 = 8) AND (r9c2 = 5) AND (r9c6 = 6) AND (r9c7 = 4) AND (r9c8 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 5) AND (r1c9 = 3) AND (r2c3 = 6) AND (r2c6 = 1) AND (r2c8 = 8) AND (r3c4 = 4) AND (r3c7 = 6) AND (r3c9 = 2) AND (r4c9 = 1) AND (r5c4 = 9) AND (r5c6 = 8) AND (r5c7 = 5) AND (r6c5 = 3) AND (r6c6 = 6) AND (r6c7 = 8) AND (r7c1 = 4) AND (r7c7 = 1) AND (r7c8 = 9) AND (r8c1 = 8) AND (r8c3 = 5) AND (r8c5 = 1) AND (r8c8 = 4) AND (r9c4 = 6) AND (r9c6 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 9) AND (r1c5 = 3) AND (r2c3 = 6) AND (r2c4 = 2) AND (r2c6 = 8) AND (r3c4 = 9) AND (r3c5 = 7) AND (r3c9 = 5) AND (r5c1 = 2) AND (r5c3 = 9) AND (r5c4 = 8) AND (r5c6 = 3) AND (r6c4 = 6) AND (r6c6 = 7) AND (r6c9 = 9) AND (r7c1 = 7) AND (r7c2 = 5) AND (r7c8 = 8) AND (r7c9 = 4) AND (r8c2 = 4) AND (r8c3 = 8) AND (r8c5 = 5) AND (r8c7 = 6) AND (r8c9 = 3) AND (r9c3 = 2) AND (r9c8 = 5) AND (r9c9 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 1) AND (r1c5 = 2) AND (r2c4 = 1) AND (r2c9 = 8) AND (r3c2 = 8) AND (r3c4 = 3) AND (r3c6 = 7) AND (r3c8 = 1) AND (r4c2 = 5) AND (r4c3 = 7) AND (r4c8 = 3) AND (r5c3 = 2) AND (r5c7 = 6) AND (r6c1 = 8) AND (r6c7 = 5) AND (r6c8 = 7) AND (r6c9 = 4) AND (r7c2 = 7) AND (r7c9 = 3) AND (r8c3 = 4) AND (r8c4 = 7) AND (r8c7 = 1) AND (r8c8 = 2) AND (r9c1 = 2) AND (r9c3 = 5) AND (r9c7 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 8) AND (r1c2 = 1) AND (r1c6 = 3) AND (r1c7 = 9) AND (r2c2 = 6) AND (r2c8 = 8) AND (r2c9 = 2) AND (r3c1 = 2) AND (r3c4 = 7) AND (r3c7 = 3) AND (r4c2 = 8) AND (r4c5 = 3) AND (r4c6 = 6) AND (r5c2 = 9) AND (r5c5 = 1) AND (r5c7 = 4) AND (r5c8 = 3) AND (r6c3 = 6) AND (r6c6 = 9) AND (r7c3 = 2) AND (r8c5 = 8) AND (r8c8 = 7) AND (r9c9 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 7) AND (r1c5 = 8) AND (r1c7 = 4) AND (r2c1 = 3) AND (r2c9 = 2) AND (r4c1 = 1) AND (r4c3 = 6) AND (r4c4 = 3) AND (r5c7 = 8) AND (r5c8 = 5) AND (r6c1 = 2) AND (r7c2 = 8) AND (r7c3 = 4) AND (r7c8 = 3) AND (r8c4 = 2) AND (r8c6 = 1) AND (r9c5 = 5);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 4) AND (r1c3 = 9) AND (r2c6 = 7) AND (r3c2 = 6) AND (r3c7 = 4) AND (r4c1 = 9) AND (r4c2 = 1) AND (r4c4 = 7) AND (r4c8 = 3) AND (r4c9 = 6) AND (r5c4 = 3) AND (r5c5 = 5) AND (r5c7 = 1) AND (r5c8 = 4) AND (r6c1 = 2) AND (r7c4 = 5) AND (r7c8 = 7) AND (r8c2 = 3) AND (r8c3 = 6) AND (r8c5 = 2) AND (r9c2 = 2) AND (r9c4 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c5 = 5) AND (r1c8 = 4) AND (r1c9 = 6) AND (r2c6 = 1) AND (r2c8 = 7) AND (r3c1 = 3) AND (r3c3 = 6) AND (r3c6 = 9) AND (r3c7 = 5) AND (r3c9 = 1) AND (r4c2 = 5) AND (r4c5 = 9) AND (r4c6 = 4) AND (r5c4 = 2) AND (r6c1 = 9) AND (r6c5 = 7) AND (r6c9 = 3) AND (r7c1 = 4) AND (r7c5 = 6) AND (r7c6 = 7) AND (r7c8 = 2) AND (r7c9 = 5) AND (r9c1 = 6) AND (r9c4 = 5) AND (r9c5 = 1) AND (r9c6 = 3) AND (r9c9 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 7) AND (r1c4 = 2) AND (r1c6 = 4) AND (r1c8 = 1) AND (r2c1 = 4) AND (r2c2 = 9) AND (r2c4 = 1) AND (r2c6 = 7) AND (r2c8 = 5) AND (r2c9 = 2) AND (r3c5 = 5) AND (r4c1 = 1) AND (r4c2 = 3) AND (r4c8 = 9) AND (r4c9 = 7) AND (r5c3 = 9) AND (r5c7 = 2) AND (r6c1 = 5) AND (r6c2 = 4) AND (r6c8 = 6) AND (r6c9 = 3) AND (r7c5 = 2) AND (r8c1 = 2) AND (r8c2 = 5) AND (r8c4 = 7) AND (r8c6 = 1) AND (r8c8 = 8) AND (r8c9 = 6) AND (r9c2 = 1) AND (r9c4 = 6) AND (r9c6 = 3) AND (r9c8 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 5) AND (r1c6 = 2) AND (r1c9 = 4) AND (r2c1 = 7) AND (r2c3 = 2) AND (r2c6 = 4) AND (r2c7 = 3) AND (r2c8 = 5) AND (r3c2 = 1) AND (r3c6 = 3) AND (r3c7 = 9) AND (r4c1 = 3) AND (r4c3 = 7) AND (r4c4 = 5) AND (r4c6 = 8) AND (r4c7 = 2) AND (r6c7 = 7) AND (r6c9 = 8) AND (r7c2 = 7) AND (r7c3 = 1) AND (r7c5 = 8) AND (r7c6 = 5) AND (r7c7 = 4) AND (r8c1 = 4) AND (r8c3 = 3) AND (r8c9 = 2) AND (r9c1 = 2) AND (r9c3 = 8) AND (r9c5 = 3) AND (r9c9 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 8) AND (r1c8 = 1) AND (r2c6 = 2) AND (r2c8 = 3) AND (r2c9 = 4) AND (r3c3 = 2) AND (r3c5 = 5) AND (r4c4 = 4) AND (r4c8 = 6) AND (r5c3 = 7) AND (r5c7 = 8) AND (r6c2 = 5) AND (r7c5 = 7) AND (r7c7 = 5) AND (r8c1 = 9) AND (r8c2 = 4) AND (r8c4 = 1) AND (r9c2 = 6) AND (r9c9 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c9 = 1) AND (r2c6 = 4) AND (r2c8 = 8) AND (r3c2 = 4) AND (r3c4 = 6) AND (r3c6 = 1) AND (r3c8 = 2) AND (r4c1 = 5) AND (r4c2 = 6) AND (r4c3 = 2) AND (r4c5 = 7) AND (r4c7 = 3) AND (r4c8 = 4) AND (r5c1 = 1) AND (r5c3 = 7) AND (r5c6 = 3) AND (r5c9 = 2) AND (r6c1 = 4) AND (r6c2 = 3) AND (r6c5 = 6) AND (r6c8 = 7) AND (r7c9 = 7) AND (r8c6 = 6) AND (r8c7 = 8) AND (r8c9 = 4) AND (r9c1 = 3) AND (r9c4 = 8) AND (r9c6 = 7) AND (r9c7 = 2) AND (r9c8 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c6 = 3) AND (r2c1 = 7) AND (r2c7 = 8) AND (r2c8 = 5) AND (r3c2 = 8) AND (r3c4 = 4) AND (r3c5 = 9) AND (r3c8 = 7) AND (r4c3 = 4) AND (r5c2 = 3) AND (r5c4 = 1) AND (r5c5 = 8) AND (r6c1 = 6) AND (r6c3 = 9) AND (r6c9 = 4) AND (r8c3 = 6) AND (r8c5 = 5) AND (r8c9 = 3) AND (r9c5 = 6) AND (r9c9 = 1);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 9) AND (r1c6 = 4) AND (r1c8 = 8) AND (r1c9 = 6) AND (r2c3 = 6) AND (r2c4 = 3) AND (r2c7 = 7) AND (r3c2 = 4) AND (r3c3 = 8) AND (r3c8 = 3) AND (r3c9 = 5) AND (r4c2 = 9) AND (r4c4 = 4) AND (r5c3 = 1) AND (r6c1 = 4) AND (r6c3 = 5) AND (r6c4 = 9) AND (r6c6 = 6) AND (r7c1 = 7) AND (r7c2 = 8) AND (r7c3 = 4) AND (r7c5 = 6) AND (r7c6 = 9) AND (r7c9 = 3) AND (r8c6 = 3) AND (r9c1 = 6) AND (r9c4 = 1) AND (r9c5 = 4) AND (r9c6 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 5) AND (r1c4 = 9) AND (r1c7 = 1) AND (r2c4 = 4) AND (r2c7 = 9) AND (r3c1 = 6) AND (r3c2 = 3) AND (r3c5 = 2) AND (r3c7 = 5) AND (r4c1 = 4) AND (r4c9 = 6) AND (r5c3 = 1) AND (r5c5 = 3) AND (r6c8 = 3) AND (r6c9 = 4) AND (r7c1 = 7) AND (r7c2 = 2) AND (r7c4 = 6) AND (r8c4 = 7) AND (r9c8 = 5);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 2) AND (r1c5 = 1) AND (r1c7 = 4) AND (r2c3 = 3) AND (r2c5 = 9) AND (r2c7 = 2) AND (r2c8 = 5) AND (r3c1 = 7) AND (r3c3 = 5) AND (r4c4 = 9) AND (r4c7 = 6) AND (r4c9 = 3) AND (r5c1 = 9) AND (r6c3 = 2) AND (r6c6 = 5) AND (r7c5 = 2) AND (r7c8 = 4) AND (r8c6 = 9) AND (r8c8 = 2) AND (r8c9 = 7) AND (r9c3 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 3) AND (r1c6 = 5) AND (r2c1 = 4) AND (r2c4 = 8) AND (r2c5 = 6) AND (r2c6 = 9) AND (r2c9 = 5) AND (r3c1 = 8) AND (r4c3 = 9) AND (r4c6 = 2) AND (r4c8 = 5) AND (r4c9 = 6) AND (r5c1 = 1) AND (r5c3 = 2) AND (r5c8 = 3) AND (r6c1 = 6) AND (r6c2 = 8) AND (r6c4 = 9) AND (r6c5 = 3) AND (r6c8 = 2) AND (r6c9 = 4) AND (r7c2 = 3) AND (r7c3 = 8) AND (r7c4 = 6) AND (r7c9 = 9) AND (r8c1 = 5) AND (r9c3 = 6) AND (r9c9 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 7) AND (r1c9 = 1) AND (r2c3 = 2) AND (r2c4 = 9) AND (r2c8 = 5) AND (r3c1 = 8) AND (r3c7 = 4) AND (r4c3 = 6) AND (r4c4 = 2) AND (r4c5 = 5) AND (r5c6 = 7) AND (r6c4 = 3) AND (r6c6 = 6) AND (r6c8 = 9) AND (r7c1 = 4) AND (r7c7 = 7) AND (r8c2 = 1) AND (r8c9 = 8) AND (r9c3 = 5) AND (r9c5 = 3) AND (r9c8 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 3) AND (r1c4 = 5) AND (r1c8 = 8) AND (r2c1 = 7) AND (r2c5 = 2) AND (r3c3 = 9) AND (r3c6 = 7) AND (r4c4 = 2) AND (r4c6 = 1) AND (r5c1 = 5) AND (r5c2 = 2) AND (r6c2 = 4) AND (r6c5 = 8) AND (r6c7 = 7) AND (r7c4 = 3) AND (r7c8 = 2) AND (r8c5 = 9) AND (r8c6 = 8) AND (r8c7 = 3) AND (r9c2 = 1) AND (r9c3 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 8) AND (r1c2 = 1) AND (r1c3 = 2) AND (r1c5 = 3) AND (r2c1 = 4) AND (r2c7 = 5) AND (r3c4 = 7) AND (r3c7 = 2) AND (r3c8 = 3) AND (r4c1 = 2) AND (r4c4 = 8) AND (r4c5 = 5) AND (r5c1 = 3) AND (r5c4 = 1) AND (r5c5 = 6) AND (r5c6 = 7) AND (r5c7 = 8) AND (r5c9 = 5) AND (r6c4 = 4) AND (r6c8 = 7) AND (r6c9 = 6) AND (r7c1 = 1) AND (r7c5 = 7) AND (r8c2 = 6) AND (r8c3 = 5) AND (r8c9 = 8) AND (r9c9 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c7 = 8) AND (r2c1 = 2) AND (r2c2 = 8) AND (r2c3 = 3) AND (r2c7 = 4) AND (r2c8 = 1) AND (r3c4 = 2) AND (r4c3 = 1) AND (r4c4 = 3) AND (r4c9 = 6) AND (r5c3 = 2) AND (r5c4 = 1) AND (r5c6 = 6) AND (r5c8 = 5) AND (r5c9 = 4) AND (r6c6 = 5) AND (r6c8 = 7) AND (r7c1 = 1) AND (r7c3 = 5) AND (r8c4 = 4) AND (r8c8 = 3) AND (r8c9 = 1) AND (r9c1 = 3) AND (r9c3 = 8) AND (r9c6 = 1) AND (r9c7 = 6) AND (r9c8 = 2) AND (r9c9 = 5);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c6 = 5) AND (r1c9 = 1) AND (r2c2 = 6) AND (r2c5 = 7) AND (r2c7 = 2) AND (r3c2 = 1) AND (r3c3 = 7) AND (r4c3 = 3) AND (r4c4 = 5) AND (r4c5 = 2) AND (r5c4 = 8) AND (r5c5 = 3) AND (r5c7 = 1) AND (r5c9 = 4) AND (r7c4 = 7) AND (r7c9 = 5) AND (r8c3 = 2) AND (r8c6 = 1) AND (r8c9 = 3) AND (r9c1 = 3) AND (r9c2 = 4) AND (r9c9 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 7) AND (r1c4 = 5) AND (r1c6 = 8) AND (r1c8 = 6) AND (r2c1 = 8) AND (r2c5 = 1) AND (r2c9 = 7) AND (r3c2 = 9) AND (r3c8 = 8) AND (r4c3 = 8) AND (r4c4 = 6) AND (r4c6 = 9) AND (r4c7 = 7) AND (r5c2 = 5) AND (r5c3 = 9) AND (r5c4 = 2) AND (r5c6 = 7) AND (r5c7 = 8) AND (r5c8 = 1) AND (r6c3 = 7) AND (r6c4 = 1) AND (r6c6 = 3) AND (r6c7 = 5) AND (r7c2 = 3) AND (r7c8 = 4) AND (r8c1 = 7) AND (r8c5 = 6) AND (r8c9 = 2) AND (r9c2 = 6) AND (r9c4 = 8) AND (r9c6 = 4) AND (r9c8 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 8) AND (r1c7 = 7) AND (r1c8 = 4) AND (r2c1 = 5) AND (r2c3 = 1) AND (r3c1 = 3) AND (r3c8 = 9) AND (r4c2 = 9) AND (r4c4 = 2) AND (r4c7 = 5) AND (r5c4 = 6) AND (r5c5 = 8) AND (r6c7 = 3) AND (r7c5 = 3) AND (r7c6 = 1) AND (r8c2 = 2) AND (r8c9 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 3) AND (r1c7 = 5) AND (r1c9 = 9) AND (r2c1 = 9) AND (r2c2 = 8) AND (r2c3 = 6) AND (r2c5 = 2) AND (r2c7 = 3) AND (r3c3 = 2) AND (r3c9 = 1) AND (r4c7 = 1) AND (r4c8 = 7) AND (r5c4 = 5) AND (r5c6 = 7) AND (r7c1 = 7) AND (r7c6 = 3) AND (r7c7 = 8) AND (r7c8 = 6) AND (r8c3 = 8) AND (r8c4 = 2) AND (r8c5 = 6) AND (r9c2 = 5) AND (r9c9 = 3);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 4) AND (r1c9 = 3) AND (r2c2 = 2) AND (r2c5 = 5) AND (r2c9 = 9) AND (r3c2 = 9) AND (r3c3 = 5) AND (r3c5 = 3) AND (r3c8 = 8) AND (r4c4 = 4) AND (r6c1 = 6) AND (r6c6 = 9) AND (r6c7 = 7) AND (r7c1 = 4) AND (r7c4 = 7) AND (r7c7 = 6) AND (r7c8 = 2) AND (r8c4 = 6) AND (r8c9 = 5) AND (r9c1 = 3) AND (r9c4 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 9) AND (r2c5 = 6) AND (r2c8 = 1) AND (r3c6 = 5) AND (r4c2 = 1) AND (r4c6 = 9) AND (r5c1 = 8) AND (r5c5 = 4) AND (r6c1 = 4) AND (r6c2 = 2) AND (r6c4 = 8) AND (r6c8 = 3) AND (r7c4 = 9) AND (r7c7 = 5) AND (r7c9 = 3) AND (r8c2 = 8) AND (r8c3 = 5) AND (r8c4 = 3) AND (r8c9 = 1) AND (r9c4 = 1) AND (r9c6 = 2) AND (r9c8 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c8 = 1) AND (r2c1 = 3) AND (r2c2 = 2) AND (r2c4 = 9) AND (r2c9 = 5) AND (r3c2 = 8) AND (r3c4 = 4) AND (r3c5 = 5) AND (r4c3 = 2) AND (r4c4 = 5) AND (r4c6 = 3) AND (r5c8 = 5) AND (r5c9 = 9) AND (r6c1 = 7) AND (r6c9 = 3) AND (r7c3 = 7) AND (r8c1 = 5) AND (r8c5 = 4) AND (r8c7 = 1) AND (r9c2 = 9) AND (r9c3 = 1) AND (r9c4 = 3) AND (r9c7 = 5) AND (r9c8 = 2) AND (r9c9 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 8) AND (r1c4 = 5) AND (r1c8 = 4) AND (r2c1 = 5) AND (r2c4 = 3) AND (r2c6 = 8) AND (r3c1 = 2) AND (r3c7 = 9) AND (r4c2 = 6) AND (r4c5 = 7) AND (r5c1 = 4) AND (r5c2 = 3) AND (r5c7 = 6) AND (r6c3 = 5) AND (r6c5 = 8) AND (r7c3 = 9) AND (r7c9 = 6) AND (r8c1 = 7) AND (r8c7 = 5) AND (r9c2 = 8) AND (r9c4 = 4) AND (r9c6 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 9) AND (r1c4 = 3) AND (r1c6 = 5) AND (r1c7 = 7) AND (r2c2 = 3) AND (r2c4 = 8) AND (r2c9 = 2) AND (r3c3 = 8) AND (r3c5 = 2) AND (r3c7 = 6) AND (r4c3 = 2) AND (r4c8 = 9) AND (r4c9 = 7) AND (r5c2 = 7) AND (r5c3 = 6) AND (r5c5 = 5) AND (r5c7 = 1) AND (r6c2 = 8) AND (r6c7 = 3) AND (r7c4 = 9) AND (r7c9 = 1) AND (r8c6 = 1) AND (r9c8 = 6);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 1) AND (r1c6 = 6) AND (r1c9 = 7) AND (r2c2 = 2) AND (r2c4 = 5) AND (r2c7 = 8) AND (r3c3 = 9) AND (r3c4 = 7) AND (r3c9 = 6) AND (r4c1 = 7) AND (r4c3 = 5) AND (r5c3 = 1) AND (r5c5 = 3) AND (r5c7 = 2) AND (r5c8 = 9) AND (r7c5 = 9) AND (r7c6 = 5) AND (r8c1 = 2) AND (r8c9 = 3) AND (r9c1 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 2) AND (r1c2 = 9) AND (r1c4 = 1) AND (r1c5 = 4) AND (r2c5 = 5) AND (r2c6 = 8) AND (r3c1 = 1) AND (r3c2 = 8) AND (r3c5 = 6) AND (r3c7 = 5) AND (r4c1 = 8) AND (r4c9 = 2) AND (r5c2 = 1) AND (r5c4 = 7) AND (r5c9 = 6) AND (r6c7 = 7) AND (r6c8 = 9) AND (r7c1 = 4) AND (r7c7 = 2) AND (r7c8 = 1) AND (r8c9 = 9) AND (r9c1 = 7) AND (r9c4 = 2) AND (r9c7 = 4) AND (r9c9 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 6) AND (r1c3 = 1) AND (r1c5 = 9) AND (r3c1 = 9) AND (r3c3 = 7) AND (r3c5 = 4) AND (r3c8 = 6) AND (r4c3 = 8) AND (r4c8 = 4) AND (r5c1 = 7) AND (r5c2 = 3) AND (r5c3 = 2) AND (r5c8 = 9) AND (r6c1 = 1) AND (r6c8 = 7) AND (r7c2 = 8) AND (r7c3 = 4) AND (r7c4 = 6) AND (r7c5 = 1) AND (r7c9 = 9) AND (r8c1 = 2) AND (r8c3 = 9) AND (r8c5 = 8) AND (r8c6 = 4) AND (r8c7 = 3) AND (r9c5 = 2) AND (r9c6 = 7) AND (r9c8 = 8) AND (r9c9 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 4) AND (r1c6 = 1) AND (r1c8 = 2) AND (r2c8 = 3) AND (r2c9 = 4) AND (r3c3 = 5) AND (r3c5 = 6) AND (r4c4 = 3) AND (r4c9 = 7) AND (r5c3 = 1) AND (r5c7 = 6) AND (r6c1 = 6) AND (r6c6 = 2) AND (r7c5 = 4) AND (r7c7 = 1) AND (r8c1 = 9) AND (r8c2 = 7) AND (r9c2 = 3) AND (r9c4 = 5);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 8) AND (r1c2 = 9) AND (r2c1 = 3) AND (r2c3 = 6) AND (r2c5 = 4) AND (r3c2 = 1) AND (r3c3 = 4) AND (r4c2 = 7) AND (r4c9 = 1) AND (r5c3 = 1) AND (r5c5 = 6) AND (r6c1 = 2) AND (r6c6 = 7) AND (r6c7 = 9) AND (r6c9 = 8) AND (r7c1 = 7) AND (r7c4 = 6) AND (r7c5 = 2) AND (r7c6 = 1) AND (r7c7 = 8) AND (r7c9 = 3) AND (r8c4 = 7) AND (r8c6 = 3) AND (r8c7 = 4) AND (r8c8 = 9) AND (r9c2 = 3) AND (r9c5 = 8) AND (r9c6 = 9) AND (r9c8 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 4) AND (r2c2 = 4) AND (r2c5 = 7) AND (r2c8 = 3) AND (r2c9 = 6) AND (r3c1 = 2) AND (r3c5 = 3) AND (r3c6 = 6) AND (r3c8 = 8) AND (r4c4 = 1) AND (r4c5 = 4) AND (r4c9 = 7) AND (r5c1 = 1) AND (r5c6 = 3) AND (r5c8 = 6) AND (r6c4 = 6) AND (r6c8 = 2) AND (r7c1 = 3) AND (r7c5 = 5) AND (r7c8 = 1) AND (r8c2 = 5) AND (r8c4 = 7) AND (r8c5 = 8) AND (r8c6 = 2) AND (r9c9 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 8) AND (r1c8 = 1) AND (r2c6 = 2) AND (r2c8 = 3) AND (r2c9 = 4) AND (r3c3 = 5) AND (r3c5 = 6) AND (r4c4 = 4) AND (r4c8 = 7) AND (r5c3 = 2) AND (r5c7 = 6) AND (r6c2 = 1) AND (r6c6 = 5) AND (r7c5 = 8) AND (r7c7 = 2) AND (r8c1 = 7) AND (r8c2 = 3) AND (r8c4 = 1) AND (r9c2 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 8) AND (r1c4 = 4) AND (r1c5 = 3) AND (r1c7 = 9) AND (r1c8 = 1) AND (r2c1 = 3) AND (r2c5 = 9) AND (r3c2 = 4) AND (r3c4 = 7) AND (r3c6 = 1) AND (r3c9 = 6) AND (r4c2 = 7) AND (r4c4 = 1) AND (r4c5 = 4) AND (r4c7 = 5) AND (r5c1 = 6) AND (r5c3 = 3) AND (r6c1 = 5) AND (r6c2 = 1) AND (r6c8 = 8) AND (r7c1 = 7) AND (r7c3 = 6) AND (r7c4 = 8) AND (r7c8 = 9) AND (r8c2 = 3) AND (r8c4 = 9) AND (r9c2 = 9) AND (r9c4 = 3) AND (r9c9 = 8);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 7) AND (r1c3 = 1) AND (r1c4 = 2) AND (r1c5 = 5) AND (r1c8 = 8) AND (r2c1 = 8) AND (r2c3 = 6) AND (r2c5 = 7) AND (r2c6 = 4) AND (r2c9 = 5) AND (r3c2 = 9) AND (r3c3 = 4) AND (r3c6 = 6) AND (r3c7 = 7) AND (r5c3 = 8) AND (r5c4 = 6) AND (r5c6 = 5) AND (r5c9 = 9) AND (r6c4 = 8) AND (r6c5 = 2) AND (r6c6 = 1) AND (r6c8 = 4) AND (r6c9 = 6) AND (r7c1 = 6) AND (r7c6 = 8) AND (r7c9 = 1) AND (r8c1 = 1) AND (r8c3 = 9) AND (r8c9 = 7) AND (r9c2 = 4);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 1) AND (r1c5 = 5) AND (r1c7 = 6) AND (r2c1 = 8) AND (r2c3 = 7) AND (r3c1 = 3) AND (r4c4 = 7) AND (r4c6 = 8) AND (r4c8 = 3) AND (r5c2 = 1) AND (r5c7 = 4) AND (r7c2 = 4) AND (r7c5 = 6) AND (r7c7 = 2) AND (r8c1 = 5) AND (r8c8 = 8) AND (r9c4 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 7) AND (r1c5 = 9) AND (r1c7 = 2) AND (r2c3 = 6) AND (r2c7 = 3) AND (r2c9 = 8) AND (r3c2 = 5) AND (r3c5 = 8) AND (r3c6 = 3) AND (r3c8 = 7) AND (r3c9 = 9) AND (r4c3 = 4) AND (r4c4 = 3) AND (r4c7 = 7) AND (r4c8 = 6) AND (r5c7 = 8) AND (r5c9 = 2) AND (r6c1 = 5) AND (r6c2 = 6) AND (r8c2 = 8) AND (r8c3 = 9) AND (r8c4 = 5) AND (r8c6 = 6) AND (r9c1 = 3) AND (r9c2 = 2) AND (r9c9 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c3 = 2) AND (r1c4 = 8) AND (r1c6 = 1) AND (r1c7 = 5) AND (r1c8 = 4) AND (r2c5 = 3) AND (r3c4 = 4) AND (r3c5 = 6) AND (r3c6 = 5) AND (r4c1 = 8) AND (r4c3 = 3) AND (r4c6 = 9) AND (r4c7 = 4) AND (r4c9 = 5) AND (r5c2 = 5) AND (r5c6 = 3) AND (r5c9 = 1) AND (r6c3 = 6) AND (r6c7 = 3) AND (r7c4 = 2) AND (r7c6 = 4) AND (r8c3 = 5) AND (r8c5 = 1) AND (r8c6 = 8) AND (r8c7 = 6) AND (r8c8 = 2) AND (r9c3 = 9) AND (r9c5 = 5);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c4 = 1) AND (r2c1 = 1) AND (r2c2 = 2) AND (r2c5 = 9) AND (r2c8 = 7) AND (r3c5 = 7) AND (r3c6 = 6) AND (r5c2 = 6) AND (r5c5 = 3) AND (r5c6 = 9) AND (r5c8 = 1) AND (r6c1 = 5) AND (r6c3 = 9) AND (r6c4 = 4) AND (r6c6 = 7) AND (r6c8 = 2) AND (r7c3 = 2) AND (r7c6 = 3) AND (r7c7 = 4) AND (r7c8 = 5) AND (r8c1 = 6) AND (r8c4 = 7) AND (r8c5 = 2) AND (r8c8 = 3) AND (r8c9 = 9) AND (r9c2 = 7) AND (r9c4 = 9) AND (r9c5 = 4) AND (r9c6 = 1) AND (r9c8 = 6) AND (r9c9 = 2);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 2) AND (r2c3 = 5) AND (r2c5 = 3) AND (r2c6 = 9) AND (r2c7 = 8) AND (r3c1 = 8) AND (r3c2 = 4) AND (r3c3 = 9) AND (r3c5 = 7) AND (r4c3 = 7) AND (r4c4 = 3) AND (r4c5 = 2) AND (r4c6 = 6) AND (r5c4 = 7) AND (r5c5 = 4) AND (r5c6 = 8) AND (r5c9 = 3) AND (r6c6 = 5) AND (r7c3 = 3) AND (r7c5 = 6) AND (r7c9 = 5) AND (r8c2 = 5) AND (r8c4 = 9) AND (r8c8 = 6) AND (r9c1 = 4) AND (r9c3 = 8) AND (r9c5 = 5) AND (r9c6 = 7) AND (r9c8 = 3) AND (r9c9 = 9);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 1) AND (r1c2 = 9) AND (r2c1 = 8) AND (r2c5 = 7) AND (r2c8 = 1) AND (r2c9 = 6) AND (r3c2 = 7) AND (r3c4 = 2) AND (r3c7 = 5) AND (r3c9 = 3) AND (r4c8 = 2) AND (r4c9 = 7) AND (r5c2 = 3) AND (r5c9 = 8) AND (r6c1 = 9) AND (r6c3 = 5) AND (r7c2 = 1) AND (r7c3 = 8) AND (r7c6 = 2) AND (r7c8 = 3) AND (r8c9 = 2) AND (r9c2 = 6) AND (r9c5 = 1) AND (r9c8 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c1 = 8) AND (r1c3 = 5) AND (r1c9 = 2) AND (r2c4 = 9) AND (r2c6 = 1) AND (r3c1 = 3) AND (r4c2 = 6) AND (r4c4 = 7) AND (r4c7 = 4) AND (r5c1 = 2) AND (r5c5 = 5) AND (r6c8 = 6) AND (r7c4 = 3) AND (r7c5 = 8) AND (r8c2 = 1) AND (r8c7 = 9) AND (r9c2 = 4) AND (r9c8 = 7);
SELECT * FROM sudoku_memory_combined_view WHERE (r1c2 = 8) AND (r2c1 = 1) AND (r2c3 = 7) AND (r2c7 = 8) AND (r2c9 = 3) AND (r3c6 = 6) AND (r3c9 = 1) AND (r4c2 = 2) AND (r5c1 = 3) AND (r5c5 = 1) AND (r6c3 = 8) AND (r6c4 = 5) AND (r6c7 = 6) AND (r6c8 = 9) AND (r7c5 = 3) AND (r7c6 = 7) AND (r7c7 = 9) AND (r8c6 = 1) AND (r9c1 = 5) AND (r9c2 = 9);
UPDATE tests SET fin = NOW() WHERE fin IS NULL;
SELECT TO_SECONDS(fin) - TO_SECONDS(debut) FROM tests;

6. Gosser à la main!

Maintenant que nous avons un échantillon représentatif et significatif et tout ce qu’il nous faut pour mesurer, de façon répétable et facile, chacun des changements que nous voulons effectuer, nous sommes en mesure de vérifier l’impact de 2 variables importantes : optimizer_search_depth et join_buffer_size.

Tout d’abord, la variable optimizer_search_depth dont voici les différents résultats :

optimizer_search_depth_table

Il est clair que cette variable a un impact majeur.  Nous savons maintenant que la valeur optimale de cette variable (dans notre cas précis) est 1.

optimizer_search_depth

On serait tenté de croire que la variable join_buffer_size pourrait avoir un impact non négligeable mais ce n’est pas le cas ici.

join_buffer_size_table

Les différences de temps (hormis pour la valeur 2Mb) ne sont pas assez significatives pour indiquer une tendance.  Malgré tout, théoriquement, cette variable devrait avoir un impact.  Pour les biens de la cause, autant avoir plus de mémoire que moins pour cette variable!  Je vous recommande donc 128Mb (plus, dans notre cas, serait un gaspillage de mémoire).

join_buffer_size

Finalement, pour mettre en valeur la différence entre une solution utilisant une table sur disque versus notre solution finale (une table en mémoire), l’histogramme suivant parle de lui-même!

engine_type

Voilà!  CQFD. En espérant que cette série d’articles vous aura permis de constater que parfois, il est nécessaire de penser out of the box et d’envisager des solutions saugrenues pour arriver à ses fins.

7. Ressources et outils

Quelques-unes des ressources et des outils utilisés dans le cadre de cette série d’articles:

setbb.com : des forums de discussion sur le sudoku (en anglais) pour les programmeurs

enjoysudoku.com : des forums de discussions (en anglais) variés et nombreux sur les sudokus

QQWing : un outil (en ligne de commande) permettant de solutionner et de générer des grilles de sudoku

SudoCue : une application permettant de solutionner et générer des sudokus

Sudoku Explainer : une application permettant de solutionner et générer des sudokus

R : langage de programmation et environnement mathématique utilisé pour le traitement de données et l’analyse statistique

db4free.net : un serveur MySQL vous permettant de créer une base de donnée gratuitement et d’expérimenter

Pharo : un environnement de développement Smalltalk


Comment presser un citron (deuxième partie)

8 janvier 2012

Dans le premier article, nous avons vu combien il était facile de solutionner des grilles de sudoku avec une seule requête SQL. Malheureusement, c’était trop beau pour être vrai…

Avant de poursuivre, voici un outil utile pour se faciliter la tâche.  Pour ceux qui utilisent Smalltalk, vous pouvez vous aider du script suivant :


| uneTableOuVue uneStringSudoku stream estLePremier |

uneTableOuVue := 'sudoku_rows_view'.
uneStringSudoku := '.........134825697759364182397182564.........581476239825641973976538421.........'.

stream := ReadWriteStream on: String new.
stream
nextPutAll: 'SELECT * '; cr;
nextPutAll: 'FROM ';
nextPutAll: uneTableOuVue;
space; cr;
nextPutAll: 'WHERE'; cr.

estLePremier := false.
1 to: 9 do: [:r |
1 to: 9 do: [:c | | i |
i := (r-1)*9 + c.
((uneStringSudoku at: i) ~= $. and: [(uneStringSudoku at: i) ~= 0])
ifTrue: [    estLePremier ifTrue: [stream nextPutAll: ' AND ';cr].
estLePremier := true.
stream
nextPutAll: '(r'; nextPutAll: r asString;
nextPutAll: 'c'; nextPutAll: c asString;
nextPutAll: ' = ';
nextPutAll: (uneStringSudoku at: i) asString;
nextPutAll: ')'.
].]].
Transcript cr;show: stream contents

Ce script génère  les requêtes SQL à partir d’une chaîne de caractères (uneStringSudoku) représentant une grille de sudoku pour une table/vue précise (uneTableOuVue) en affichant le résultat dans le Transcript.

1. Problème majeur

Il y a une faille majeure et évidente dans la solution telle que présentée : elle repose totalement sur la capacité de MySQL de faire correspondre les révélés (givens en anglais) de la grille à des lignes. Que se passerait-il si une ligne (ou pire encore, plusieurs lignes) dans le sudoku ne contenait pas de révélés (ou pas assez)? Sans index à utiliser, une lecture séquentielle de la table nous attend sans doute! Prenons, par exemple, la grille suivante:

Ce sudoku contient 54 révélés (la première grille n’en comptait que 30, près de la moitié de celle-ci) et 6 de ses lignes seront rapidement récupérées avec les index.  De plus, il y a suffisamment de révélés pour éliminer rapidement un bon nombre de lignes candidates avec les contraintes du puzzle incluses dans la vue sudoku_rows_view.

Cependant les lignes vides (1, 5 et 9) causeront probablement une lecture séquentielle (table scan) de la table.  Nous faisons face à un problème majeur avec les lignes 1, 5 et 9 étant vides! Examinons la requête pour ce sudoku :

EXPLAIN
SELECT *
FROM sudoku_rows_view
WHERE
(r2c1 = 1) AND (r2c2 = 3) AND (r2c3 = 4) AND (r2c4 = 8) AND
(r2c5 = 2) AND (r2c6 = 5) AND (r2c7 = 6) AND (r2c8 = 9) AND
(r2c9 = 7) AND (r3c1 = 7) AND (r3c2 = 5) AND (r3c3 = 9) AND
(r3c4 = 3) AND (r3c5 = 6) AND (r3c6 = 4) AND (r3c7 = 1) AND
(r3c8 = 8) AND (r3c9 = 2) AND (r4c1 = 3) AND (r4c2 = 9) AND
(r4c3 = 7) AND (r4c4 = 1) AND (r4c5 = 8) AND (r4c6 = 2) AND
(r4c7 = 5) AND (r4c8 = 6) AND (r4c9 = 4) AND (r6c1 = 5) AND
(r6c2 = 8) AND (r6c3 = 1) AND (r6c4 = 4) AND (r6c5 = 7) AND
(r6c6 = 6) AND (r6c7 = 2) AND (r6c8 = 3) AND (r6c9 = 9) AND
(r7c1 = 8) AND (r7c2 = 2) AND (r7c3 = 5) AND (r7c4 = 6) AND
(r7c5 = 4) AND (r7c6 = 1) AND (r7c7 = 9) AND (r7c8 = 7) AND
(r7c9 = 3) AND (r8c1 = 9) AND (r8c2 = 7) AND (r8c3 = 6) AND
(r8c4 = 5) AND (r8c5 = 3) AND (r8c6 = 8) AND (r8c7 = 4) AND
(r8c8 = 2) AND (r8c9 = 1);

Le résultat du EXPLAIN :

+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+------+--------+----------------------------------------------------------------------------------+
| id | select_type | table | type        | possible_keys                                                                                                                                      | key         | key_len | ref  | rows   | Extra                                                                            |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+------+--------+----------------------------------------------------------------------------------+
|  1 | SIMPLE      | r2    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i37,i29     | 2,2     | NULL |     68 | Using intersect(i37,i29); Using where                                            |
|  1 | SIMPLE      | r3    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i37,i28     | 2,2     | NULL |     68 | Using intersect(i37,i28); Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | r4    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i56,i29     | 2,2     | NULL |     68 | Using intersect(i56,i29); Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | r6    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12,i35     | 2,2     | NULL |     68 | Using intersect(i12,i35); Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | r7    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12,i68     | 2,2     | NULL |     68 | Using intersect(i12,i68); Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | r8    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i37,i79,i38 | 2,2,2   | NULL |     78 | Using intersect(i37,i79,i38); Using where; Using join buffer (Block Nested Loop) |
|  1 | SIMPLE      | r1    | range       | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23         | 1       | NULL |  40012 | Using index condition; Using where; Using join buffer (Block Nested Loop)        |
|  1 | SIMPLE      | r5    | ALL         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | NULL        | NULL    | NULL | 362880 | Using where; Using join buffer (Block Nested Loop)                               |
|  1 | SIMPLE      | r9    | ALL         | NULL                                                                                                                                               | NULL        | NULL    | NULL | 362880 | Using where; Using join buffer (Block Nested Loop)                               |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+------+--------+----------------------------------------------------------------------------------+
9 rows in set (13.39 sec)

Les lignes vides (lignes 1, 5 et 9) nous feront payer très chèrement le fait que nous ne pouvons pas utiliser pleinement les index! Il n’y a qu’à constater le nombre de lignes à potentiellement examiner pour joindre les tables r1, r5 et r9 (40012 x 362880 x 362880 = 5268855958732800) ainsi que le type de jointure utilisé (range, ALL et ALL).

Vérifions en combien de temps la requête s’exécute :


+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| r1c1 | r1c2 | r1c3 | r1c4 | r1c5 | r1c6 | r1c7 | r1c8 | r1c9 | r2c1 | r2c2 | r2c3 | r2c4 | r2c5 | r2c6 | r2c7 | r2c8 | r2c9 | r3c1 | r3c2 | r3c3 | r3c4 | r3c5 | r3c6 | r3c7 | r3c8 | r3c9 | r4c1 | r4c2 | r4c3 | r4c4 | r4c5 | r4c6 | r4c7 | r4c8 | r4c9 | r5c1 | r5c2 | r5c3 | r5c4 | r5c5 | r5c6 | r5c7 | r5c8 | r5c9 | r6c1 | r6c2 | r6c3 | r6c4 | r6c5 | r6c6 | r6c7 | r6c8 | r6c9 | r7c1 | r7c2 | r7c3 | r7c4 | r7c5 | r7c6 | r7c7 | r7c8 | r7c9 | r8c1 | r8c2 | r8c3 | r8c4 | r8c5 | r8c6 | r8c7 | r8c8 | r8c9 | r9c1 | r9c2 | r9c3 | r9c4 | r9c5 | r9c6 | r9c7 | r9c8 | r9c9 |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
|    2 |    6 |    8 |    7 |    1 |    9 |    3 |    4 |    5 |    1 |    3 |    4 |    8 |    2 |    5 |    6 |    9 |    7 |    7 |    5 |    9 |    3 |    6 |    4 |    1 |    8 |    2 |    3 |    9 |    7 |    1 |    8 |    2 |    5 |    6 |    4 |    6 |    4 |    2 |    9 |    5 |    3 |    7 |    1 |    8 |    5 |    8 |    1 |    4 |    7 |    6 |    2 |    3 |    9 |    8 |    2 |    5 |    6 |    4 |    1 |    9 |    7 |    3 |    9 |    7 |    6 |    5 |    3 |    8 |    4 |    2 |    1 |    4 |    1 |    3 |    2 |    9 |    7 |    8 |    5 |    6 |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
1 row in set (6.17 sec)

Ouf!  Nous sommes passés de 0.39 seconde (grille 01) à 6.17 secondes (grille 02) malgré le fait que la grille 02 comporte près de 2 fois plus de révélés que la grille 01!  Cet exemple démontre clairement que les choses peuvent rapidement mal tourner à un rythme alarmant (même exponentiel) quand nous sommes confrontés à une grille contenant des lignes vides ou presque vides!

2. Changer de point de vue!

Imaginons maintenant que nous faisons effectuer une rotation à notre grille et que les colonnes deviennent des lignes.  Dans ce cas, chaque nouvelle ligne pourrait dès lors bénéficier des index!

Voyons cette nouvelle grille :

La requête aurait désormais l’air de ceci :


SELECT *
FROM sudoku_rows_view
WHERE
(r1c2 = 1) AND (r1c3 = 7) AND (r1c4 = 3) AND (r1c6 = 5) AND
(r1c7 = 8) AND (r1c8 = 9) AND (r2c2 = 3) AND (r2c3 = 5) AND
(r2c4 = 9) AND (r2c6 = 8) AND (r2c7 = 2) AND (r2c8 = 7) AND
(r3c2 = 4) AND (r3c3 = 9) AND (r3c4 = 7) AND (r3c6 = 1) AND
(r3c7 = 5) AND (r3c8 = 6) AND (r4c2 = 8) AND (r4c3 = 3) AND
(r4c4 = 1) AND (r4c6 = 4) AND (r4c7 = 6) AND (r4c8 = 5) AND
(r5c2 = 2) AND (r5c3 = 6) AND (r5c4 = 8) AND (r5c6 = 7) AND
(r5c7 = 4) AND (r5c8 = 3) AND (r6c2 = 5) AND (r6c3 = 4) AND
(r6c4 = 2) AND (r6c6 = 6) AND (r6c7 = 1) AND (r6c8 = 8) AND
(r7c2 = 6) AND (r7c3 = 1) AND (r7c4 = 5) AND (r7c6 = 2) AND
(r7c7 = 9) AND (r7c8 = 4) AND (r8c2 = 9) AND (r8c3 = 8) AND
(r8c4 = 6) AND (r8c6 = 3) AND (r8c7 = 7) AND (r8c8 = 2) AND
(r9c2 = 7) AND (r9c3 = 2) AND (r9c4 = 4) AND (r9c6 = 9) AND
(r9c7 = 3) AND (r9c8 = 1);

Le résultat du EXPLAIN correspondant :


+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+------+------+----------------------------------------------------------------------------------+
| id | select_type | table | type        | possible_keys                                                                                                                                      | key         | key_len | ref  | rows | Extra                                                                            |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+------+------+----------------------------------------------------------------------------------+
|  1 | SIMPLE      | r3    | index_merge | i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i67,i68,i69,i78,i79,i89                                                    | i23,i38,i48 | 2,2,2   | NULL |   64 | Using intersect(i23,i38,i48); Using where                                        |
|  1 | SIMPLE      | r9    | index_merge | i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i67,i68,i69,i78,i79,i89                                                    | i78,i68,i48 | 2,2,2   | NULL |   65 | Using intersect(i78,i68,i48); Using where; Using join buffer (Block Nested Loop) |
|  1 | SIMPLE      | r1    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i67     | 2,2     | NULL |   68 | Using intersect(i23,i67); Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | r2    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i68     | 2,2     | NULL |   68 | Using intersect(i23,i68); Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | r4    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i78,i46     | 2,2     | NULL |   68 | Using intersect(i78,i46); Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | r5    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i68     | 2,2     | NULL |   68 | Using intersect(i23,i68); Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | r6    | index_merge | i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i67,i68,i69,i78,i79,i89                                                    | i23,i67     | 2,2     | NULL |   68 | Using intersect(i23,i67); Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | r7    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i68     | 2,2     | NULL |   68 | Using intersect(i23,i68); Using where; Using join buffer (Block Nested Loop)     |
|  1 | SIMPLE      | r8    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i37,i24     | 2,2     | NULL |   68 | Using intersect(i37,i24); Using where; Using join buffer (Block Nested Loop)     |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+------+------+----------------------------------------------------------------------------------+
9 rows in set (42.98 sec)

Et combien de temps la requête prendrait-elle à s’exécuter?

SELECT *
FROM sudoku_rows_view
WHERE
(r1c2 = 1) AND (r1c3 = 7) AND (r1c4 = 3) AND (r1c6 = 5) AND
(r1c7 = 8) AND (r1c8 = 9) AND (r2c2 = 3) AND (r2c3 = 5) AND
(r2c4 = 9) AND (r2c6 = 8) AND (r2c7 = 2) AND (r2c8 = 7) AND
(r3c2 = 4) AND (r3c3 = 9) AND (r3c4 = 7) AND (r3c6 = 1) AND
(r3c7 = 5) AND (r3c8 = 6) AND (r4c2 = 8) AND (r4c3 = 3) AND
(r4c4 = 1) AND (r4c6 = 4) AND (r4c7 = 6) AND (r4c8 = 5) AND
(r5c2 = 2) AND (r5c3 = 6) AND (r5c4 = 8) AND (r5c6 = 7) AND
(r5c7 = 4) AND (r5c8 = 3) AND (r6c2 = 5) AND (r6c3 = 4) AND
(r6c4 = 2) AND (r6c6 = 6) AND (r6c7 = 1) AND (r6c8 = 8) AND
(r7c2 = 6) AND (r7c3 = 1) AND (r7c4 = 5) AND (r7c6 = 2) AND
(r7c7 = 9) AND (r7c8 = 4) AND (r8c2 = 9) AND (r8c3 = 8) AND
(r8c4 = 6) AND (r8c6 = 3) AND (r8c7 = 7) AND (r8c8 = 2) AND
(r9c2 = 7) AND (r9c3 = 2) AND (r9c4 = 4) AND (r9c6 = 9) AND
(r9c7 = 3) AND (r9c8 = 1);
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| r1c1 | r1c2 | r1c3 | r1c4 | r1c5 | r1c6 | r1c7 | r1c8 | r1c9 | r2c1 | r2c2 | r2c3 | r2c4 | r2c5 | r2c6 | r2c7 | r2c8 | r2c9 | r3c1 | r3c2 | r3c3 | r3c4 | r3c5 | r3c6 | r3c7 | r3c8 | r3c9 | r4c1 | r4c2 | r4c3 | r4c4 | r4c5 | r4c6 | r4c7 | r4c8 | r4c9 | r5c1 | r5c2 | r5c3 | r5c4 | r5c5 | r5c6 | r5c7 | r5c8 | r5c9 | r6c1 | r6c2 | r6c3 | r6c4 | r6c5 | r6c6 | r6c7 | r6c8 | r6c9 | r7c1 | r7c2 | r7c3 | r7c4 | r7c5 | r7c6 | r7c7 | r7c8 | r7c9 | r8c1 | r8c2 | r8c3 | r8c4 | r8c5 | r8c6 | r8c7 | r8c8 | r8c9 | r9c1 | r9c2 | r9c3 | r9c4 | r9c5 | r9c6 | r9c7 | r9c8 | r9c9 |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
|    2 |    1 |    7 |    3 |    6 |    5 |    8 |    9 |    4 |    6 |    3 |    5 |    9 |    4 |    8 |    2 |    7 |    1 |    8 |    4 |    9 |    7 |    2 |    1 |    5 |    6 |    3 |    7 |    8 |    3 |    1 |    9 |    4 |    6 |    5 |    2 |    1 |    2 |    6 |    8 |    5 |    7 |    4 |    3 |    9 |    9 |    5 |    4 |    2 |    3 |    6 |    1 |    8 |    7 |    3 |    6 |    1 |    5 |    7 |    2 |    9 |    4 |    8 |    4 |    9 |    8 |    6 |    1 |    3 |    7 |    2 |    5 |    5 |    7 |    2 |    4 |    8 |    9 |    3 |    1 |    6 |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
1 row in set (0.22 sec)

Nous sommes passés de 6.17 secondes à 0.22 seconde! Un gain imposant!

3. Les vues combinées

Alors pourquoi ne tenterions-nous pas de résoudre nos sudokus en effectuant la recherche par ligne ET par colonne à la fois?

Nous allons donc construire une seconde vue (sudoku_columns_view) qui sera basée sur les colonnes de la grille.  Pour faire résoudre les sudokus, il nous faudra une troisième vue (sudoku_combined_view) qui combinera la vue par lignes (sudoku_rows_view) avec la vue par colonne (sudoku_columns_view).  De cette façon, nous serons à l’abri des grilles avec des lignes vides et des grilles avec des colonnes vides.  L’optimisateur de requête aura dorénavant tout le luxe de choisir la « méthode » la plus efficace!

Construisons la vue par colonnes en exécutant cette requête :

USE sudoku;

CREATE VIEW sudoku_columns_view AS
SELECT
col1.c1 as r1c1, col1.c2 as r2c1, col1.c3 as r3c1, col1.c4 as r4c1, col1.c5 as r5c1,col1.c6 as r6c1, col1.c7 as r7c1, col1.c8 as r8c1, col1.c9 as r9c1, col2.c1 as r1c2,
col2.c2 as r2c2, col2.c3 as r3c2, col2.c4 as r4c2, col2.c5 as r5c2, col2.c6 as r6c2,col2.c7 as r7c2, col2.c8 as r8c2, col2.c9 as r9c2, col3.c1 as r1c3, col3.c2 as r2c3,
col3.c3 as r3c3, col3.c4 as r4c3, col3.c5 as r5c3, col3.c6 as r6c3, col3.c7 as r7c3,col3.c8 as r8c3, col3.c9 as r9c3, col4.c1 as r1c4, col4.c2 as r2c4, col4.c3 as r3c4,
col4.c4 as r4c4, col4.c5 as r5c4, col4.c6 as r6c4, col4.c7 as r7c4, col4.c8 as r8c4,col4.c9 as r9c4, col5.c1 as r1c5, col5.c2 as r2c5, col5.c3 as r3c5, col5.c4 as r4c5,
col5.c5 as r5c5, col5.c6 as r6c5, col5.c7 as r7c5, col5.c8 as r8c5, col5.c9 as r9c5,col6.c1 as r1c6, col6.c2 as r2c6, col6.c3 as r3c6, col6.c4 as r4c6, col6.c5 as r5c6,
col6.c6 as r6c6, col6.c7 as r7c6, col6.c8 as r8c6, col6.c9 as r9c6, col7.c1 as r1c7,col7.c2 as r2c7, col7.c3 as r3c7, col7.c4 as r4c7, col7.c5 as r5c7, col7.c6 as r6c7,
col7.c7 as r7c7, col7.c8 as r8c7, col7.c9 as r9c7, col8.c1 as r1c8, col8.c2 as r2c8,col8.c3 as r3c8, col8.c4 as r4c8, col8.c5 as r5c8, col8.c6 as r6c8, col8.c7 as r7c8,
col8.c8 as r8c8, col8.c9 as r9c8, col9.c1 as r1c9, col9.c2 as r2c9, col9.c3 as r3c9,col9.c4 as r4c9, col9.c5 as r5c9, col9.c6 as r6c9, col9.c7 as r7c9, col9.c8 as r8c9,
col9.c9 as r9c9
FROM
positions col1, positions col2, positions col3,positions col4, positions col5, positions col6,positions col7, positions col8, positions col9
WHERE
-- Nombres uniques dans chaque rangee
(col1.c1 <> col2.c1) AND (col1.c1 <> col3.c1) AND (col1.c1 <> col4.c1) AND (col1.c1 <> col5.c1) AND (col1.c1 <> col6.c1) AND (col1.c1 <> col7.c1) AND (col1.c1 <> col8.c1) AND (col1.c1 <> col9.c1) AND (col1.c2 <> col2.c2) AND (col1.c2 <> col3.c2) AND (col1.c2 <> col4.c2) AND (col1.c2 <> col5.c2) AND (col1.c2 <> col6.c2) AND (col1.c2 <> col7.c2) AND (col1.c2 <> col8.c2) AND (col1.c2 <> col9.c2) AND (col1.c3 <> col2.c3) AND (col1.c3 <> col3.c3) AND (col1.c3 <> col4.c3) AND (col1.c3 <> col5.c3) AND (col1.c3 <> col6.c3) AND (col1.c3 <> col7.c3) AND (col1.c3 <> col8.c3) AND (col1.c3 <> col9.c3) AND (col1.c4 <> col2.c4) AND (col1.c4 <> col3.c4) AND (col1.c4 <> col4.c4) AND (col1.c4 <> col5.c4) AND (col1.c4 <> col6.c4) AND (col1.c4 <> col7.c4) AND (col1.c4 <> col8.c4) AND (col1.c4 <> col9.c4) AND
(col1.c5 <> col2.c5) AND (col1.c5 <> col3.c5) AND (col1.c5 <> col4.c5) AND (col1.c5 <> col5.c5) AND (col1.c5 <> col6.c5) AND (col1.c5 <> col7.c5) AND (col1.c5 <> col8.c5) AND (col1.c5 <> col9.c5) AND (col1.c6 <> col2.c6) AND (col1.c6 <> col3.c6) AND (col1.c6 <> col4.c6) AND (col1.c6 <> col5.c6) AND (col1.c6 <> col6.c6) AND (col1.c6 <> col7.c6) AND (col1.c6 <> col8.c6) AND (col1.c6 <> col9.c6) AND (col1.c7 <> col2.c7) AND (col1.c7 <> col3.c7) AND (col1.c7 <> col4.c7) AND (col1.c7 <> col5.c7) AND (col1.c7 <> col6.c7) AND (col1.c7 <> col7.c7) AND (col1.c7 <> col8.c7) AND (col1.c7 <> col9.c7) AND (col1.c8 <> col2.c8) AND (col1.c8 <> col3.c8) AND (col1.c8 <> col4.c8) AND (col1.c8 <> col5.c8) AND (col1.c8 <> col6.c8) AND (col1.c8 <> col7.c8) AND (col1.c8 <> col8.c8) AND (col1.c8 <> col9.c8) AND
(col1.c9 <> col2.c9) AND (col1.c9 <> col3.c9) AND (col1.c9 <> col4.c9) AND (col1.c9 <> col5.c9) AND (col1.c9 <> col6.c9) AND (col1.c9 <> col7.c9) AND (col1.c9 <> col8.c9) AND (col1.c9 <> col9.c9) AND (col2.c1 <> col3.c1) AND (col2.c1 <> col4.c1) AND (col2.c1 <> col5.c1) AND (col2.c1 <> col6.c1) AND (col2.c1 <> col7.c1) AND (col2.c1 <> col8.c1) AND (col2.c1 <> col9.c1) AND (col2.c2 <> col3.c2) AND (col2.c2 <> col4.c2) AND (col2.c2 <> col5.c2) AND (col2.c2 <> col6.c2) AND (col2.c2 <> col7.c2) AND (col2.c2 <> col8.c2) AND (col2.c2 <> col9.c2) AND (col2.c3 <> col3.c3) AND (col2.c3 <> col4.c3) AND (col2.c3 <> col5.c3) AND (col2.c3 <> col6.c3) AND (col2.c3 <> col7.c3) AND (col2.c3 <> col8.c3) AND (col2.c3 <> col9.c3) AND (col2.c4 <> col3.c4) AND (col2.c4 <> col4.c4) AND (col2.c4 <> col5.c4) AND
(col2.c4 <> col6.c4) AND (col2.c4 <> col7.c4) AND (col2.c4 <> col8.c4) AND (col2.c4 <> col9.c4) AND (col2.c5 <> col3.c5) AND (col2.c5 <> col4.c5) AND (col2.c5 <> col5.c5) AND (col2.c5 <> col6.c5) AND (col2.c5 <> col7.c5) AND (col2.c5 <> col8.c5) AND (col2.c5 <> col9.c5) AND (col2.c6 <> col3.c6) AND (col2.c6 <> col4.c6) AND (col2.c6 <> col5.c6) AND (col2.c6 <> col6.c6) AND (col2.c6 <> col7.c6) AND (col2.c6 <> col8.c6) AND (col2.c6 <> col9.c6) AND (col2.c7 <> col3.c7) AND (col2.c7 <> col4.c7) AND (col2.c7 <> col5.c7) AND (col2.c7 <> col6.c7) AND (col2.c7 <> col7.c7) AND (col2.c7 <> col8.c7) AND (col2.c7 <> col9.c7) AND (col2.c8 <> col3.c8) AND (col2.c8 <> col4.c8) AND (col2.c8 <> col5.c8) AND (col2.c8 <> col6.c8) AND (col2.c8 <> col7.c8) AND (col2.c8 <> col8.c8) AND (col2.c8 <> col9.c8) AND
(col2.c9 <> col3.c9) AND (col2.c9 <> col4.c9) AND (col2.c9 <> col5.c9) AND (col2.c9 <> col6.c9) AND (col2.c9 <> col7.c9) AND (col2.c9 <> col8.c9) AND (col2.c9 <> col9.c9) AND (col3.c1 <> col4.c1) AND (col3.c1 <> col5.c1) AND (col3.c1 <> col6.c1) AND (col3.c1 <> col7.c1) AND (col3.c1 <> col8.c1) AND (col3.c1 <> col9.c1) AND (col3.c2 <> col4.c2) AND (col3.c2 <> col5.c2) AND (col3.c2 <> col6.c2) AND (col3.c2 <> col7.c2) AND (col3.c2 <> col8.c2) AND (col3.c2 <> col9.c2) AND (col3.c3 <> col4.c3) AND (col3.c3 <> col5.c3) AND (col3.c3 <> col6.c3) AND (col3.c3 <> col7.c3) AND (col3.c3 <> col8.c3) AND (col3.c3 <> col9.c3) AND (col3.c4 <> col4.c4) AND (col3.c4 <> col5.c4) AND (col3.c4 <> col6.c4) AND (col3.c4 <> col7.c4) AND (col3.c4 <> col8.c4) AND (col3.c4 <> col9.c4) AND (col3.c5 <> col4.c5) AND
(col3.c5 <> col5.c5) AND (col3.c5 <> col6.c5) AND (col3.c5 <> col7.c5) AND (col3.c5 <> col8.c5) AND (col3.c5 <> col9.c5) AND (col3.c6 <> col4.c6) AND (col3.c6 <> col5.c6) AND (col3.c6 <> col6.c6) AND (col3.c6 <> col7.c6) AND (col3.c6 <> col8.c6) AND (col3.c6 <> col9.c6) AND (col3.c7 <> col4.c7) AND (col3.c7 <> col5.c7) AND (col3.c7 <> col6.c7) AND (col3.c7 <> col7.c7) AND (col3.c7 <> col8.c7) AND (col3.c7 <> col9.c7) AND (col3.c8 <> col4.c8) AND (col3.c8 <> col5.c8) AND (col3.c8 <> col6.c8) AND (col3.c8 <> col7.c8) AND (col3.c8 <> col8.c8) AND (col3.c8 <> col9.c8) AND (col3.c9 <> col4.c9) AND (col3.c9 <> col5.c9) AND (col3.c9 <> col6.c9) AND (col3.c9 <> col7.c9) AND (col3.c9 <> col8.c9) AND (col3.c9 <> col9.c9) AND (col4.c1 <> col5.c1) AND (col4.c1 <> col6.c1) AND (col4.c1 <> col7.c1) AND
(col4.c1 <> col8.c1) AND (col4.c1 <> col9.c1) AND (col4.c2 <> col5.c2) AND (col4.c2 <> col6.c2) AND (col4.c2 <> col7.c2) AND (col4.c2 <> col8.c2) AND (col4.c2 <> col9.c2) AND (col4.c3 <> col5.c3) AND (col4.c3 <> col6.c3) AND (col4.c3 <> col7.c3) AND (col4.c3 <> col8.c3) AND (col4.c3 <> col9.c3) AND (col4.c4 <> col5.c4) AND (col4.c4 <> col6.c4) AND (col4.c4 <> col7.c4) AND (col4.c4 <> col8.c4) AND (col4.c4 <> col9.c4) AND (col4.c5 <> col5.c5) AND (col4.c5 <> col6.c5) AND (col4.c5 <> col7.c5) AND (col4.c5 <> col8.c5) AND (col4.c5 <> col9.c5) AND (col4.c6 <> col5.c6) AND (col4.c6 <> col6.c6) AND (col4.c6 <> col7.c6) AND (col4.c6 <> col8.c6) AND (col4.c6 <> col9.c6) AND (col4.c7 <> col5.c7) AND (col4.c7 <> col6.c7) AND (col4.c7 <> col7.c7) AND (col4.c7 <> col8.c7) AND (col4.c7 <> col9.c7) AND
(col4.c8 <> col5.c8) AND (col4.c8 <> col6.c8) AND (col4.c8 <> col7.c8) AND (col4.c8 <> col8.c8) AND (col4.c8 <> col9.c8) AND (col4.c9 <> col5.c9) AND (col4.c9 <> col6.c9) AND (col4.c9 <> col7.c9) AND (col4.c9 <> col8.c9) AND (col4.c9 <> col9.c9) AND (col5.c1 <> col6.c1) AND (col5.c1 <> col7.c1) AND (col5.c1 <> col8.c1) AND (col5.c1 <> col9.c1) AND (col5.c2 <> col6.c2) AND (col5.c2 <> col7.c2) AND (col5.c2 <> col8.c2) AND (col5.c2 <> col9.c2) AND (col5.c3 <> col6.c3) AND (col5.c3 <> col7.c3) AND (col5.c3 <> col8.c3) AND (col5.c3 <> col9.c3) AND (col5.c4 <> col6.c4) AND (col5.c4 <> col7.c4) AND (col5.c4 <> col8.c4) AND (col5.c4 <> col9.c4) AND (col5.c5 <> col6.c5) AND (col5.c5 <> col7.c5) AND (col5.c5 <> col8.c5) AND (col5.c5 <> col9.c5) AND (col5.c6 <> col6.c6) AND (col5.c6 <> col7.c6) AND
(col5.c6 <> col8.c6) AND (col5.c6 <> col9.c6) AND (col5.c7 <> col6.c7) AND (col5.c7 <> col7.c7) AND (col5.c7 <> col8.c7) AND (col5.c7 <> col9.c7) AND (col5.c8 <> col6.c8) AND (col5.c8 <> col7.c8) AND (col5.c8 <> col8.c8) AND (col5.c8 <> col9.c8) AND (col5.c9 <> col6.c9) AND (col5.c9 <> col7.c9) AND (col5.c9 <> col8.c9) AND (col5.c9 <> col9.c9) AND (col6.c1 <> col7.c1) AND (col6.c1 <> col8.c1) AND (col6.c1 <> col9.c1) AND (col6.c2 <> col7.c2) AND (col6.c2 <> col8.c2) AND (col6.c2 <> col9.c2) AND (col6.c3 <> col7.c3) AND (col6.c3 <> col8.c3) AND (col6.c3 <> col9.c3) AND (col6.c4 <> col7.c4) AND (col6.c4 <> col8.c4) AND (col6.c4 <> col9.c4) AND (col6.c5 <> col7.c5) AND (col6.c5 <> col8.c5) AND (col6.c5 <> col9.c5) AND (col6.c6 <> col7.c6) AND (col6.c6 <> col8.c6) AND (col6.c6 <> col9.c6) AND
(col6.c7 <> col7.c7) AND (col6.c7 <> col8.c7) AND (col6.c7 <> col9.c7) AND (col6.c8 <> col7.c8) AND (col6.c8 <> col8.c8) AND (col6.c8 <> col9.c8) AND (col6.c9 <> col7.c9) AND (col6.c9 <> col8.c9) AND (col6.c9 <> col9.c9) AND (col7.c1 <> col8.c1) AND (col7.c1 <> col9.c1) AND (col7.c2 <> col8.c2) AND (col7.c2 <> col9.c2) AND (col7.c3 <> col8.c3) AND (col7.c3 <> col9.c3) AND (col7.c4 <> col8.c4) AND (col7.c4 <> col9.c4) AND (col7.c5 <> col8.c5) AND (col7.c5 <> col9.c5) AND (col7.c6 <> col8.c6) AND (col7.c6 <> col9.c6) AND (col7.c7 <> col8.c7) AND (col7.c7 <> col9.c7) AND (col7.c8 <> col8.c8) AND (col7.c8 <> col9.c8) AND (col7.c9 <> col8.c9) AND (col7.c9 <> col9.c9) AND (col8.c1 <> col9.c1) AND (col8.c2 <> col9.c2) AND (col8.c3 <> col9.c3) AND (col8.c4 <> col9.c4) AND (col8.c5 <> col9.c5) AND
(col8.c6 <> col9.c6) AND (col8.c7 <> col9.c7) AND (col8.c8 <> col9.c8) AND (col8.c9 <> col9.c9) AND
-- Nombres uniques dans chaque maison de 3x3
(col1.c1 <> col1.c2) AND (col1.c1 <> col1.c3) AND (col1.c1 <> col2.c2) AND (col1.c1 <> col2.c3) AND (col1.c1 <> col3.c2) AND (col1.c1 <> col3.c3) AND (col1.c2 <> col1.c3) AND (col1.c2 <> col2.c1) AND (col1.c2 <> col2.c3) AND (col1.c2 <> col3.c1) AND (col1.c2 <> col3.c3) AND (col1.c3 <> col2.c1) AND (col1.c3 <> col2.c2) AND (col1.c3 <> col3.c1) AND (col1.c3 <> col3.c2) AND (col1.c4 <> col1.c5) AND (col1.c4 <> col1.c6) AND (col1.c4 <> col2.c5) AND (col1.c4 <> col2.c6) AND (col1.c4 <> col3.c5) AND (col1.c4 <> col3.c6) AND (col1.c5 <> col1.c6) AND (col1.c5 <> col2.c4) AND (col1.c5 <> col2.c6) AND (col1.c5 <> col3.c4) AND (col1.c5 <> col3.c6) AND (col1.c6 <> col2.c4) AND (col1.c6 <> col2.c5) AND (col1.c6 <> col3.c4) AND (col1.c6 <> col3.c5) AND (col1.c7 <> col1.c8) AND (col1.c7 <> col1.c9) AND
(col1.c7 <> col2.c8) AND (col1.c7 <> col2.c9) AND (col1.c7 <> col3.c8) AND (col1.c7 <> col3.c9) AND (col1.c8 <> col1.c9) AND (col1.c8 <> col2.c7) AND (col1.c8 <> col2.c9) AND (col1.c8 <> col3.c7) AND (col1.c8 <> col3.c9) AND (col1.c9 <> col2.c7) AND (col1.c9 <> col2.c8) AND (col1.c9 <> col3.c7) AND (col1.c9 <> col3.c8) AND (col2.c1 <> col2.c2) AND (col2.c1 <> col2.c3) AND (col2.c1 <> col3.c2) AND (col2.c1 <> col3.c3) AND (col2.c2 <> col2.c3) AND (col2.c2 <> col3.c1) AND (col2.c2 <> col3.c3) AND (col2.c3 <> col3.c1) AND (col2.c3 <> col3.c2) AND (col2.c4 <> col2.c5) AND (col2.c4 <> col2.c6) AND (col2.c4 <> col3.c5) AND (col2.c4 <> col3.c6) AND (col2.c5 <> col2.c6) AND (col2.c5 <> col3.c4) AND (col2.c5 <> col3.c6) AND (col2.c6 <> col3.c4) AND (col2.c6 <> col3.c5) AND (col2.c7 <> col2.c8) AND
(col2.c7 <> col2.c9) AND (col2.c7 <> col3.c8) AND (col2.c7 <> col3.c9) AND (col2.c8 <> col2.c9) AND (col2.c8 <> col3.c7) AND (col2.c8 <> col3.c9) AND (col2.c9 <> col3.c7) AND (col2.c9 <> col3.c8) AND (col3.c1 <> col3.c2) AND (col3.c1 <> col3.c3) AND (col3.c2 <> col3.c3) AND (col3.c4 <> col3.c5) AND (col3.c4 <> col3.c6) AND (col3.c5 <> col3.c6) AND (col3.c7 <> col3.c8) AND (col3.c7 <> col3.c9) AND (col3.c8 <> col3.c9) AND (col4.c1 <> col4.c2) AND (col4.c1 <> col4.c3) AND (col4.c1 <> col5.c2) AND (col4.c1 <> col5.c3) AND (col4.c1 <> col6.c2) AND (col4.c1 <> col6.c3) AND (col4.c2 <> col4.c3) AND (col4.c2 <> col5.c1) AND (col4.c2 <> col5.c3) AND (col4.c2 <> col6.c1) AND (col4.c2 <> col6.c3) AND (col4.c3 <> col5.c1) AND (col4.c3 <> col5.c2) AND (col4.c3 <> col6.c1) AND (col4.c3 <> col6.c2) AND
(col4.c4 <> col4.c5) AND (col4.c4 <> col4.c6) AND (col4.c4 <> col5.c5) AND (col4.c4 <> col5.c6) AND (col4.c4 <> col6.c5) AND (col4.c4 <> col6.c6) AND (col4.c5 <> col4.c6) AND (col4.c5 <> col5.c4) AND (col4.c5 <> col5.c6) AND (col4.c5 <> col6.c4) AND (col4.c5 <> col6.c6) AND (col4.c6 <> col5.c4) AND (col4.c6 <> col5.c5) AND (col4.c6 <> col6.c4) AND (col4.c6 <> col6.c5) AND (col4.c7 <> col4.c8) AND (col4.c7 <> col4.c9) AND (col4.c7 <> col5.c8) AND (col4.c7 <> col5.c9) AND (col4.c7 <> col6.c8) AND (col4.c7 <> col6.c9) AND (col4.c8 <> col4.c9) AND (col4.c8 <> col5.c7) AND (col4.c8 <> col5.c9) AND (col4.c8 <> col6.c7) AND (col4.c8 <> col6.c9) AND (col4.c9 <> col5.c7) AND (col4.c9 <> col5.c8) AND (col4.c9 <> col6.c7) AND (col4.c9 <> col6.c8) AND (col5.c1 <> col5.c2) AND (col5.c1 <> col5.c3) AND
(col5.c1 <> col6.c2) AND (col5.c1 <> col6.c3) AND (col5.c2 <> col5.c3) AND (col5.c2 <> col6.c1) AND (col5.c2 <> col6.c3) AND (col5.c3 <> col6.c1) AND (col5.c3 <> col6.c2) AND (col5.c4 <> col5.c5) AND (col5.c4 <> col5.c6) AND (col5.c4 <> col6.c5) AND (col5.c4 <> col6.c6) AND (col5.c5 <> col5.c6) AND (col5.c5 <> col6.c4) AND (col5.c5 <> col6.c6) AND (col5.c6 <> col6.c4) AND (col5.c6 <> col6.c5) AND (col5.c7 <> col5.c8) AND (col5.c7 <> col5.c9) AND (col5.c7 <> col6.c8) AND (col5.c7 <> col6.c9) AND (col5.c8 <> col5.c9) AND (col5.c8 <> col6.c7) AND (col5.c8 <> col6.c9) AND (col5.c9 <> col6.c7) AND (col5.c9 <> col6.c8) AND (col6.c1 <> col6.c2) AND (col6.c1 <> col6.c3) AND (col6.c2 <> col6.c3) AND (col6.c4 <> col6.c5) AND (col6.c4 <> col6.c6) AND (col6.c5 <> col6.c6) AND (col6.c7 <> col6.c8) AND
(col6.c7 <> col6.c9) AND (col6.c8 <> col6.c9) AND (col7.c1 <> col7.c2) AND (col7.c1 <> col7.c3) AND (col7.c1 <> col8.c2) AND (col7.c1 <> col8.c3) AND (col7.c1 <> col9.c2) AND (col7.c1 <> col9.c3) AND (col7.c2 <> col7.c3) AND (col7.c2 <> col8.c1) AND (col7.c2 <> col8.c3) AND (col7.c2 <> col9.c1) AND (col7.c2 <> col9.c3) AND (col7.c3 <> col8.c1) AND (col7.c3 <> col8.c2) AND (col7.c3 <> col9.c1) AND (col7.c3 <> col9.c2) AND (col7.c4 <> col7.c5) AND (col7.c4 <> col7.c6) AND (col7.c4 <> col8.c5) AND (col7.c4 <> col8.c6) AND (col7.c4 <> col9.c5) AND (col7.c4 <> col9.c6) AND (col7.c5 <> col7.c6) AND (col7.c5 <> col8.c4) AND (col7.c5 <> col8.c6) AND (col7.c5 <> col9.c4) AND (col7.c5 <> col9.c6) AND (col7.c6 <> col8.c4) AND (col7.c6 <> col8.c5) AND (col7.c6 <> col9.c4) AND (col7.c6 <> col9.c5) AND
(col7.c7 <> col7.c8) AND (col7.c7 <> col7.c9) AND (col7.c7 <> col8.c8) AND (col7.c7 <> col8.c9) AND (col7.c7 <> col9.c8) AND (col7.c7 <> col9.c9) AND (col7.c8 <> col7.c9) AND (col7.c8 <> col8.c7) AND (col7.c8 <> col8.c9) AND (col7.c8 <> col9.c7) AND (col7.c8 <> col9.c9) AND (col7.c9 <> col8.c7) AND (col7.c9 <> col8.c8) AND (col7.c9 <> col9.c7) AND (col7.c9 <> col9.c8) AND (col8.c1 <> col8.c2) AND (col8.c1 <> col8.c3) AND (col8.c1 <> col9.c2) AND (col8.c1 <> col9.c3) AND (col8.c2 <> col8.c3) AND (col8.c2 <> col9.c1) AND (col8.c2 <> col9.c3) AND (col8.c3 <> col9.c1) AND (col8.c3 <> col9.c2) AND (col8.c4 <> col8.c5) AND (col8.c4 <> col8.c6) AND (col8.c4 <> col9.c5) AND (col8.c4 <> col9.c6) AND (col8.c5 <> col8.c6) AND (col8.c5 <> col9.c4) AND (col8.c5 <> col9.c6) AND (col8.c6 <> col9.c4) AND
(col8.c6 <> col9.c5) AND (col8.c7 <> col8.c8) AND (col8.c7 <> col8.c9) AND (col8.c7 <> col9.c8) AND (col8.c7 <> col9.c9) AND (col8.c8 <> col8.c9) AND (col8.c8 <> col9.c7) AND (col8.c8 <> col9.c9) AND (col8.c9 <> col9.c7) AND (col8.c9 <> col9.c8) AND (col9.c1 <> col9.c2) AND (col9.c1 <> col9.c3) AND (col9.c2 <> col9.c3) AND (col9.c4 <> col9.c5) AND (col9.c4 <> col9.c6) AND (col9.c5 <> col9.c6) AND (col9.c7 <> col9.c8) AND (col9.c7 <> col9.c9) AND (col9.c8 <> col9.c9);

Maintenant, chers lecteurs, patientez un peu!

ATTENTION : n’allez surtout pas essayer de solutionner une grille  avant de passer au prochain point!

Pour l’instant, contentez-vous seulement de créer la nouvelle vue sudoku_combined_view :

USE sudoku;

CREATE VIEW sudoku_combined_view AS
SELECT t1.*
FROM sudoku_rows_view t1
INNER JOIN sudoku_columns_view t2
ON

-- Jointures entre représentation-colonnes et représentation-rangées
(t1.r1c1 = t2.r1c1) AND (t1.r1c2 = t2.r1c2) AND (t1.r1c3 = t2.r1c3) AND (t1.r1c4 = t2.r1c4) AND
(t1.r1c5 = t2.r1c5) AND (t1.r1c6 = t2.r1c6) AND (t1.r1c7 = t2.r1c7) AND (t1.r1c8 = t2.r1c8) AND
(t1.r1c9 = t2.r1c9) AND (t1.r2c1 = t2.r2c1) AND (t1.r2c2 = t2.r2c2) AND (t1.r2c3 = t2.r2c3) AND
(t1.r2c4 = t2.r2c4) AND (t1.r2c5 = t2.r2c5) AND (t1.r2c6 = t2.r2c6) AND (t1.r2c7 = t2.r2c7) AND
(t1.r2c8 = t2.r2c8) AND (t1.r2c9 = t2.r2c9) AND (t1.r3c1 = t2.r3c1) AND (t1.r3c2 = t2.r3c2) AND
(t1.r3c3 = t2.r3c3) AND (t1.r3c4 = t2.r3c4) AND (t1.r3c5 = t2.r3c5) AND (t1.r3c6 = t2.r3c6) AND
(t1.r3c7 = t2.r3c7) AND (t1.r3c8 = t2.r3c8) AND (t1.r3c9 = t2.r3c9) AND (t1.r4c1 = t2.r4c1) AND
(t1.r4c2 = t2.r4c2) AND (t1.r4c3 = t2.r4c3) AND (t1.r4c4 = t2.r4c4) AND (t1.r4c5 = t2.r4c5) AND
(t1.r4c6 = t2.r4c6) AND (t1.r4c7 = t2.r4c7) AND (t1.r4c8 = t2.r4c8) AND (t1.r4c9 = t2.r4c9) AND
(t1.r5c1 = t2.r5c1) AND (t1.r5c2 = t2.r5c2) AND (t1.r5c3 = t2.r5c3) AND (t1.r5c4 = t2.r5c4) AND
(t1.r5c5 = t2.r5c5) AND (t1.r5c6 = t2.r5c6) AND (t1.r5c7 = t2.r5c7) AND (t1.r5c8 = t2.r5c8) AND
(t1.r5c9 = t2.r5c9) AND (t1.r6c1 = t2.r6c1) AND (t1.r6c2 = t2.r6c2) AND (t1.r6c3 = t2.r6c3) AND
(t1.r6c4 = t2.r6c4) AND (t1.r6c5 = t2.r6c5) AND (t1.r6c6 = t2.r6c6) AND (t1.r6c7 = t2.r6c7) AND
(t1.r6c8 = t2.r6c8) AND (t1.r6c9 = t2.r6c9) AND (t1.r7c1 = t2.r7c1) AND (t1.r7c2 = t2.r7c2) AND
(t1.r7c3 = t2.r7c3) AND (t1.r7c4 = t2.r7c4) AND (t1.r7c5 = t2.r7c5) AND (t1.r7c6 = t2.r7c6) AND
(t1.r7c7 = t2.r7c7) AND (t1.r7c8 = t2.r7c8) AND (t1.r7c9 = t2.r7c9) AND (t1.r8c1 = t2.r8c1) AND
(t1.r8c2 = t2.r8c2) AND (t1.r8c3 = t2.r8c3) AND (t1.r8c4 = t2.r8c4) AND (t1.r8c5 = t2.r8c5) AND
(t1.r8c6 = t2.r8c6) AND (t1.r8c7 = t2.r8c7) AND (t1.r8c8 = t2.r8c8) AND (t1.r8c9 = t2.r8c9) AND
(t1.r9c1 = t2.r9c1) AND (t1.r9c2 = t2.r9c2) AND (t1.r9c3 = t2.r9c3) AND (t1.r9c4 = t2.r9c4) AND
(t1.r9c5 = t2.r9c5) AND (t1.r9c6 = t2.r9c6) AND (t1.r9c7 = t2.r9c7) AND (t1.r9c8 = t2.r9c8) AND
(t1.r9c9 = t2.r9c9);

4. L’optimisateur de plan

Avant de tenter d’exécuter la requête de la grille présentée au point 1 de cet article, quelques explications sont de mise. Il appert que notre nouvelle façon de faire change radicalement les choses!

En effet, au lieu de joindre seulement 9 tables comme c’était le cas avec sudoku_rows_view, notre nouvelle solution joint 9 tables une première fois (sudoku_rows_view), encore une fois 9 tables (sudoku_columns_view) puis regroupe les résultats de ces 2 vues dans sudoku_combined_view.

Il faut savoir que l’optimisateur de requêtes de MySQL, par défaut, énumère toutes les jointures possibles pour déterminer le plan d’accès qu’il considère comme optimal. Dans le cas qui nous intéresse, l’optimisateur détecte donc 18 tables indirectement référencées par la vue sudoku_combined_view et aura donc à examiner 18! (18 factorielle) jointures possibles, c’est-à-dire un total de 6402373705728000 jointures! Si par malheur vous tentiez d’exécuter la requête sur la vue sudoku_combined_view, il vous faudrait attendre une éternité avant que MySQL détermine un plan d’accès!  Pour vérifier, j’ai laissé rouler une requête de EXPLAIN sur la vue sudoku_combined_view pendant 2 jours avant de l’arrêter…

Heureusement, il existe une variable système nous permettant de contrôler le zèle de l’optimisateur de requêtes!  Cette variable s’appelle optimizer_search_depth.  Elle détermine la profondeur d’analyse de l’optimisateur quand celui-ci essaie de trouver le plan d’accès optimal.  À quoi bon un plan d’accès optimal si celui-ci prend 3 semaines à être généré ?  En ce qui nous concerne, un plan d’accès non optimal mais généré rapidement, compte tenu des 18 tables, est ce que nous recherchons!

La variable optimizer_search_depth peut être changée dans les fichiers de configuration de MySQL ou dynamiquement au beau milieu d’une session.  Prenez garde toutefois!  Si vous changez cette variable dans une session et non au niveau des fichiers de configuration, la nouvelle valeur de la variable ne s’applique qu’à la session!

Réglons cette valeur à 3  pour l’instant (plus de détails quant à cette valeur dans le prochain article)  :


set @@optimizer_search_depth = 3;

Maintenant, nous pouvons exécuter notre requête :


SELECT *
FROM sudoku_combined_view
WHERE
(r2c1 = 1) AND (r2c2 = 3) AND (r2c3 = 4) AND (r2c4 = 8) AND
(r2c5 = 2) AND (r2c6 = 5) AND (r2c7 = 6) AND (r2c8 = 9) AND
(r2c9 = 7) AND (r3c1 = 7) AND (r3c2 = 5) AND (r3c3 = 9) AND
(r3c4 = 3) AND (r3c5 = 6) AND (r3c6 = 4) AND (r3c7 = 1) AND
(r3c8 = 8) AND (r3c9 = 2) AND (r4c1 = 3) AND (r4c2 = 9) AND
(r4c3 = 7) AND (r4c4 = 1) AND (r4c5 = 8) AND (r4c6 = 2) AND
(r4c7 = 5) AND (r4c8 = 6) AND (r4c9 = 4) AND (r6c1 = 5) AND
(r6c2 = 8) AND (r6c3 = 1) AND (r6c4 = 4) AND (r6c5 = 7) AND
(r6c6 = 6) AND (r6c7 = 2) AND (r6c8 = 3) AND (r6c9 = 9) AND
(r7c1 = 8) AND (r7c2 = 2) AND (r7c3 = 5) AND (r7c4 = 6) AND
(r7c5 = 4) AND (r7c6 = 1) AND (r7c7 = 9) AND (r7c8 = 7) AND
(r7c9 = 3) AND (r8c1 = 9) AND (r8c2 = 7) AND (r8c3 = 6) AND
(r8c4 = 5) AND (r8c5 = 3) AND (r8c6 = 8) AND (r8c7 = 4) AND
(r8c8 = 2) AND (r8c9 = 1);

Fantastique!  1.08 seconde!  Est-il possible d’extraire plus de jus de ce citron?

Voyons ce que le EXPLAIN a à nous dire :

+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+-------------------------------+------+--------------------------------------------------------------+
| id | select_type | table | type        | possible_keys                                                                                                                                      | key         | key_len | ref                           | rows | Extra                                                        |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+-------------------------------+------+--------------------------------------------------------------+
|  1 | SIMPLE      | col3  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i38,i48 | 2,2,2   | NULL                          |   64 | Using intersect(i23,i38,i48); Using where                    |
|  1 | SIMPLE      | col9  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i78,i68,i48 | 2,2,2   | NULL                          |   65 | Using intersect(i78,i68,i48); Using where; Using join buffer |
|  1 | SIMPLE      | r2    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i37,i29     | 2,2     | NULL                          |   68 | Using intersect(i37,i29); Using where; Using join buffer     |
|  1 | SIMPLE      | r3    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i37,i28     | 2,2     | NULL                          |   68 | Using intersect(i37,i28); Using where; Using join buffer     |
|  1 | SIMPLE      | r4    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i56,i29     | 2,2     | NULL                          |   68 | Using intersect(i56,i29); Using where; Using join buffer     |
|  1 | SIMPLE      | r6    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12,i35     | 2,2     | NULL                          |   68 | Using intersect(i12,i35); Using where; Using join buffer     |
|  1 | SIMPLE      | r7    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12,i68     | 2,2     | NULL                          |   68 | Using intersect(i12,i68); Using where; Using join buffer     |
|  1 | SIMPLE      | col1  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i67     | 2,2     | NULL                          |   68 | Using intersect(i23,i67); Using where; Using join buffer     |
|  1 | SIMPLE      | col2  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i68     | 2,2     | NULL                          |   68 | Using intersect(i23,i68); Using where; Using join buffer     |
|  1 | SIMPLE      | col4  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i78,i46     | 2,2     | NULL                          |   68 | Using intersect(i78,i46); Using where; Using join buffer     |
|  1 | SIMPLE      | col5  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i68     | 2,2     | NULL                          |   68 | Using intersect(i23,i68); Using where; Using join buffer     |
|  1 | SIMPLE      | col6  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i67     | 2,2     | NULL                          |   68 | Using intersect(i23,i67); Using where; Using join buffer     |
|  1 | SIMPLE      | r8    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i37,i79,i38 | 2,2,2   | NULL                          |   78 | Using intersect(i37,i79,i38); Using where; Using join buffer |
|  1 | SIMPLE      | col8  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i37,i24     | 2,2     | NULL                          |   68 | Using intersect(i37,i24); Using where; Using join buffer     |
|  1 | SIMPLE      | col7  | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i23,i68     | 2,2     | NULL                          |   68 | Using intersect(i23,i68); Using where; Using join buffer     |
|  1 | SIMPLE      | r1    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12         | 2       | sudoku.col1.c1,sudoku.col2.c1 | 5040 | Using where                                                  |
|  1 | SIMPLE      | r5    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12         | 2       | sudoku.col1.c5,sudoku.col2.c5 | 5040 | Using where                                                  |
|  1 | SIMPLE      | r9    | ref         | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12         | 2       | sudoku.col1.c9,sudoku.col2.c9 | 5040 | Using where                                                  |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+-------------------------------+------+--------------------------------------------------------------+
18 rows in set (0.28 sec)

5. Optimisation de la table

Il existe quelques trucs d’optimisation de table que nous avons omis de faire.  C’est peut-être le temps d’y songer pour extraire chaque milliseconde et chaque octet possible!

Bien que la table positions ne subisse jamais de UPDATE, de INSERT ou de DELETE, sommes-nous certains que les pages d’index sont triées ? Pour ce faire, nous pourrions exécuter un OPTIMIZE TABLE sur la table positions.  Ce serait inutile dans notre cas.  Pourquoi?  Parce que les permutations générées pour créer les requêtes d’insertion dans la table positions ont été générées dans l’ordre des index.

D’autre part, comme la table n’a connu aucune modification, un ANALYZE TABLE serait, lui aussi, totalement inutile!

Changer la définition de la table avec un ALTER TABLE pour y inclure AVG_ROW_LENGTH et MAX_ROWS ?  Pas plus utile.  Comme le format des lignes dans la table positions est Fixed et que la table est de format MyISAM, ces deux valeurs n’ont pas à être forcées puisque MySQL les détermine sans notre aide!

6. Impossible n’est pas français!

Est-ce possible de faire mieux?  En éternel optimiste et têtu que je suis, je répondrai « oui » !  Mais comment?

Seulement, avons-nous tout prévu?  Que faire avec une grille contenant des lignes vides et des colonnes vides comme la grille suivante :

Suite au prochain article!


Comment presser un citron (première partie)

7 janvier 2012

Ainsi donc, cette première partie détaillera la méthode de base utilisée pour résoudre un sudoku en une seule requête SQL.  Et en passant, pour ceux que la petite histoire intéresse, vous trouverez ici un excellent article sur l’évolution du sudoku.

Pour nous faciliter la tâche, nous utiliserons des tables de type MyISAM pour commencer.  Dans le prochain article, nous ferons aussi en sorte que notre méthode ne retourne qu’une seule grille valide même dans le cas où plusieurs solutions existeraient.  Rappelons que notre objectif ultime est d’optimiser une base de données dans le but bien précis de solutionner une grille valide dans des délais raisonnables.  Mais pour cet article, nous nous contenterons de verser dans la facilité!

Si l’envie vous prenait de vous salir les mains, vous aurez besoin d’un langage de programmation (idéalement Smalltalk comme j’utilise Pharo mais Squeak ou n’importe quel autre environnement Smalltalk fera l’affaire!) pour générer vous-même certaines données.  Si ce qui vous intéresse c’est seulement le résultat, n’importe quel client MySQL pourrait faire l’affaire comme je vous fournirai tous les scripts SQL nécessaires.

Ainsi, pour la suite de cet article, vous aurez besoin d’un client MySQL.

Bien que ce qui suit puisse se faire à l’aide de vos outils favoris, je vous suggère l’invite de commande et le client MySQL par souci de simplicité et de rapidité!

1. Création de la base de données

Il nous faut tout d’abord créer la base de données en exécutant:

CREATE DATABASE sudoku;

2. Création de la table de positions

La solution (et la représentation des données que j’ai envisagée) pour résoudre ce problème est triviale : il s’agit de créer toutes les permutations possibles pour une ligne et de toutes les insérer dans une table que nous joindrons ensuite 9 fois sur elle-même de façon à créer le puzzle complet.  Évidemment,  nous devrons aussi ajouter toutes les règles nécessaires (dans une vue) pour que la grille soit valide ainsi que les valeurs de départ connues du sudoku.

Ainsi donc, comme la grille standard a 9 colonnes, il a fallu créer 9! (9 factorielle = 362880 = 9*8*7*6*5*4*3*2*1) lignes que nous avons insérées dans cette table.  Chaque enregistrement de la table positions représente une ligne de sudoku, constituée de ses 9 colonnes (de là les identifiants c1, c2, c3, c4, etc).

USE sudoku;

CREATE TABLE positions (
c1 TINYINT UNSIGNED NOT NULL,
c2 TINYINT UNSIGNED NOT NULL,
c3 TINYINT UNSIGNED NOT NULL,
c4 TINYINT UNSIGNED NOT NULL,
c5 TINYINT UNSIGNED NOT NULL,
c6 TINYINT UNSIGNED NOT NULL,
c7 TINYINT UNSIGNED NOT NULL,
c8 TINYINT UNSIGNED NOT NULL,
c9 TINYINT UNSIGNED NOT NULL
) ENGINE=MYISAM;

Vous remarquerez l’absence d’index. Pour accélérer les choses, nous définirons les index seulement une fois la table remplie!  Les index seront essentiels dans notre cas, en particulier pour ce qui nous attend dans le prochain article!

3. Générer les données

J’ai créé les requêtes pour les INSERT dans la table positions à l’aide d’un petit script exécuté dans un workspace Pharo Smalltalk.

Voici le script utilisé :


| file |
file := StandardFileStream forceNewFileNamed: 'positions.sql'.
(1 to: 9) permutationsDo: [:e | file
nextPutAll: 'INSERT INTO positions(c1,c2,c3,c4,c5,c6,c7,c8,c9) VALUES(';
nextPutAll: (e at: 1) printString;nextPut: $, ;
nextPutAll: (e at: 2) printString;nextPut: $, ;
nextPutAll: (e at: 3) printString;nextPut: $, ;
nextPutAll: (e at: 4) printString;nextPut: $, ;
nextPutAll: (e at: 5) printString;nextPut: $, ;
nextPutAll: (e at: 6) printString;nextPut: $, ;
nextPutAll: (e at: 7) printString;nextPut: $, ;
nextPutAll: (e at: 8) printString;nextPut: $, ;
nextPutAll: (e at: 9) printString;nextPutAll: ');';cr].
file close.

Pour les plus aventuriers d’entre vous, je suggère d’étudier le contenu du fichier positions.sql afin de pouvoir générer l’équivalent à l’aide de votre langage de programmation favori! Pour les autres, j’ai déjà fait le travail et vous trouverez le fichier ici.

L’exécution de ce script dans un workspace créera un fichier nommé positions.sql  contenant toutes les requêtes de INSERT servant à remplir la table positions.

ATTENTION: la prochaine étape prend quelques minutes!

Pour insérer les données dans la table positions, ouvrez un invite de commande et exécutez ceci :

4. Générer les contraintes

Les contraintes de la requête servant à solutionner la grille sudoku ont aussi été générées à l’aide d’un script exécuté dans un workspace avec Pharo. Ce script élimine toute les clauses superflues ou dupliquées de façon à garder leur nombre au strict minimum en prenant bien soin de s’assurer d’avoir une grille de sudoku valide. Plus précisément, ce script veille à :

1) éliminer les clauses dupliquées (par exemple, nul besoin de spécifier que (r1.c3 <> r2.c3) et que (r2.c3 <> r1.c3), c’est la même chose!;

2) éliminer tous les clauses reliées aux lignes comme nous savons que toutes les lignes de la table position sont valides comme nous les avons toutes générées.

| s1 s2 s3 |
s1 := Set new.
1 to: 9 do: [:r |
1 to: 9 do: [:c |    | cell |
cell := 'r', r printString, '.c', c printString.
1 to: 9 do: [:r2 |         | compCell |
compCell := 'r', r2 printString, '.c', c printString.
compCell ~= cell
ifTrue: [    cell < compCell
ifTrue: [s1 add: (cell, ' <> ', compCell)]
ifFalse: [s1 add: (compCell, ' <> ', cell)].
]
]
]
].
Transcript cr;show: '-- Unique in column';cr.
s1 asSortedCollection do: [:e | Transcript show: '(', e, ') AND ';cr].

s2 := Set new.
1 to: 9 do: [:r |
1 to: 9 do: [:c |    | cell deltaR deltaC |
deltaR := ((r-1) // 3) * 3.
deltaC := ((c-1) // 3) * 3.
1 to: 3 do: [:r2 |
1 to: 3 do: [:c2 |    | compCell |
cell := 'r', r printString, '.c', c printString.
compCell := 'r', (r2 + deltaR) printString, '.c', (c2 + deltaC) printString.
(compCell ~= cell and: [(r2 + deltaR) ~= r])
ifTrue:[    cell < compCell
ifTrue: [s2 add: (cell, ' <> ', compCell)]
ifFalse: [s2 add: (compCell, ' <> ', cell)].
]
]
]
]
].
Transcript cr;show: '-- Unique within 3x3 square';cr.
s3 := Set new.
s2 do: [:each | (s1 includes: each) ifFalse: [s3 add: each]].
s3 asSortedCollection do: [:e | Transcript show: '(', e, ') AND ';cr].

Nous utiliserons le résultat affiché dans le Transcript pour créer notre vue!

Note: il vous faudra préalablement changer une méthode dans Pharo pour être en mesure d’afficher la totalité des contraintes.

5. Créer les index

Pour accélérer la recherche, il nous faut des index! Il est temps de les générer!

ATTENTION: la prochaine étape prend plusieurs minutes!

USE sudoku;

CREATE INDEX i12 ON positions(c1, c2); CREATE INDEX i13 ON positions(c1, c3);
CREATE INDEX i14 ON positions(c1, c4); CREATE INDEX i15 ON positions(c1, c5);
CREATE INDEX i16 ON positions(c1, c6); CREATE INDEX i17 ON positions(c1, c7);
CREATE INDEX i18 ON positions(c1, c8); CREATE INDEX i19 ON positions(c1, c9);
CREATE INDEX i23 ON positions(c2, c3); CREATE INDEX i24 ON positions(c2, c4);
CREATE INDEX i25 ON positions(c2, c5); CREATE INDEX i26 ON positions(c2, c6);
CREATE INDEX i27 ON positions(c2, c7); CREATE INDEX i28 ON positions(c2, c8);
CREATE INDEX i29 ON positions(c2, c9); CREATE INDEX i34 ON positions(c3, c4);
CREATE INDEX i35 ON positions(c3, c5); CREATE INDEX i36 ON positions(c3, c6);
CREATE INDEX i37 ON positions(c3, c7); CREATE INDEX i38 ON positions(c3, c8);
CREATE INDEX i39 ON positions(c3, c9); CREATE INDEX i45 ON positions(c4, c5);
CREATE INDEX i46 ON positions(c4, c6); CREATE INDEX i47 ON positions(c4, c7);
CREATE INDEX i48 ON positions(c4, c8); CREATE INDEX i49 ON positions(c4, c9);
CREATE INDEX i56 ON positions(c5, c6); CREATE INDEX i57 ON positions(c5, c7);
CREATE INDEX i58 ON positions(c5, c8); CREATE INDEX i59 ON positions(c5, c9);
CREATE INDEX i67 ON positions(c6, c7); CREATE INDEX i68 ON positions(c6, c8);
CREATE INDEX i69 ON positions(c6, c9); CREATE INDEX i78 ON positions(c7, c8);
CREATE INDEX i79 ON positions(c7, c9); CREATE INDEX i89 ON positions(c8, c9);
CREATE INDEX i9 ON positions(c9);

6. Créer une vue pour chercher les sudokus

C’est ici que les contraintes générées précédemment à l’aide de Pharo deviennent utiles!  Observez le nombre effarant de conditions dans la clause WHERE de la requête définissant la vue!

USE sudoku;

CREATE VIEW sudoku_rows_view AS
SELECT
r1.c1 as r1c1, r1.c2 as r1c2, r1.c3 as r1c3, r1.c4 as r1c4, r1.c5 as r1c5, r1.c6 as r1c6, r1.c7 as r1c7, r1.c8 as r1c8, r1.c9 as r1c9, r2.c1 as r2c1,
r2.c2 as r2c2, r2.c3 as r2c3, r2.c4 as r2c4, r2.c5 as r2c5, r2.c6 as r2c6, r2.c7 as r2c7, r2.c8 as r2c8, r2.c9 as r2c9, r3.c1 as r3c1, r3.c2 as r3c2,
r3.c3 as r3c3, r3.c4 as r3c4, r3.c5 as r3c5, r3.c6 as r3c6, r3.c7 as r3c7, r3.c8 as r3c8, r3.c9 as r3c9, r4.c1 as r4c1, r4.c2 as r4c2, r4.c3 as r4c3,
r4.c4 as r4c4, r4.c5 as r4c5, r4.c6 as r4c6, r4.c7 as r4c7, r4.c8 as r4c8, r4.c9 as r4c9, r5.c1 as r5c1, r5.c2 as r5c2, r5.c3 as r5c3, r5.c4 as r5c4,
r5.c5 as r5c5, r5.c6 as r5c6, r5.c7 as r5c7, r5.c8 as r5c8, r5.c9 as r5c9, r6.c1 as r6c1, r6.c2 as r6c2, r6.c3 as r6c3, r6.c4 as r6c4, r6.c5 as r6c5,
r6.c6 as r6c6, r6.c7 as r6c7, r6.c8 as r6c8, r6.c9 as r6c9, r7.c1 as r7c1, r7.c2 as r7c2, r7.c3 as r7c3, r7.c4 as r7c4, r7.c5 as r7c5, r7.c6 as r7c6,
r7.c7 as r7c7, r7.c8 as r7c8, r7.c9 as r7c9, r8.c1 as r8c1, r8.c2 as r8c2, r8.c3 as r8c3, r8.c4 as r8c4, r8.c5 as r8c5, r8.c6 as r8c6, r8.c7 as r8c7,
r8.c8 as r8c8, r8.c9 as r8c9, r9.c1 as r9c1, r9.c2 as r9c2, r9.c3 as r9c3, r9.c4 as r9c4, r9.c5 as r9c5, r9.c6 as r9c6, r9.c7 as r9c7, r9.c8 as r9c8,
r9.c9 as r9c9

FROM
positions r1, positions r2, positions r3,
positions r4, positions r5, positions r6,
positions r7, positions r8, positions r9

WHERE
-- Nombres uniques dans chaque colonne
(r1.c1 <> r2.c1) AND (r1.c1 <> r3.c1) AND (r1.c1 <> r4.c1) AND (r1.c1 <> r5.c1) AND (r1.c1 <> r6.c1) AND (r1.c1 <> r7.c1) AND (r1.c1 <> r8.c1) AND (r1.c1 <> r9.c1) AND (r1.c2 <> r2.c2) AND (r1.c2 <> r3.c2) AND (r1.c2 <> r4.c2) AND (r1.c2 <> r5.c2) AND (r1.c2 <> r6.c2) AND (r1.c2 <> r7.c2) AND (r1.c2 <> r8.c2) AND (r1.c2 <> r9.c2) AND
(r1.c3 <> r2.c3) AND (r1.c3 <> r3.c3) AND (r1.c3 <> r4.c3) AND (r1.c3 <> r5.c3) AND (r1.c3 <> r6.c3) AND (r1.c3 <> r7.c3) AND (r1.c3 <> r8.c3) AND (r1.c3 <> r9.c3) AND (r1.c4 <> r2.c4) AND (r1.c4 <> r3.c4) AND (r1.c4 <> r4.c4) AND (r1.c4 <> r5.c4) AND (r1.c4 <> r6.c4) AND (r1.c4 <> r7.c4) AND (r1.c4 <> r8.c4) AND (r1.c4 <> r9.c4) AND
(r1.c5 <> r2.c5) AND (r1.c5 <> r3.c5) AND (r1.c5 <> r4.c5) AND (r1.c5 <> r5.c5) AND (r1.c5 <> r6.c5) AND (r1.c5 <> r7.c5) AND (r1.c5 <> r8.c5) AND (r1.c5 <> r9.c5) AND (r1.c6 <> r2.c6) AND (r1.c6 <> r3.c6) AND (r1.c6 <> r4.c6) AND (r1.c6 <> r5.c6) AND (r1.c6 <> r6.c6) AND (r1.c6 <> r7.c6) AND (r1.c6 <> r8.c6) AND (r1.c6 <> r9.c6) AND
(r1.c7 <> r2.c7) AND (r1.c7 <> r3.c7) AND (r1.c7 <> r4.c7) AND (r1.c7 <> r5.c7) AND (r1.c7 <> r6.c7) AND (r1.c7 <> r7.c7) AND (r1.c7 <> r8.c7) AND (r1.c7 <> r9.c7) AND (r1.c8 <> r2.c8) AND (r1.c8 <> r3.c8) AND (r1.c8 <> r4.c8) AND (r1.c8 <> r5.c8) AND (r1.c8 <> r6.c8) AND (r1.c8 <> r7.c8) AND (r1.c8 <> r8.c8) AND (r1.c8 <> r9.c8) AND
(r1.c9 <> r2.c9) AND (r1.c9 <> r3.c9) AND (r1.c9 <> r4.c9) AND (r1.c9 <> r5.c9) AND (r1.c9 <> r6.c9) AND (r1.c9 <> r7.c9) AND (r1.c9 <> r8.c9) AND (r1.c9 <> r9.c9) AND (r2.c1 <> r3.c1) AND (r2.c1 <> r4.c1) AND (r2.c1 <> r5.c1) AND (r2.c1 <> r6.c1) AND (r2.c1 <> r7.c1) AND (r2.c1 <> r8.c1) AND (r2.c1 <> r9.c1) AND (r2.c2 <> r3.c2) AND
(r2.c2 <> r4.c2) AND (r2.c2 <> r5.c2) AND (r2.c2 <> r6.c2) AND (r2.c2 <> r7.c2) AND (r2.c2 <> r8.c2) AND (r2.c2 <> r9.c2) AND (r2.c3 <> r3.c3) AND (r2.c3 <> r4.c3) AND (r2.c3 <> r5.c3) AND (r2.c3 <> r6.c3) AND (r2.c3 <> r7.c3) AND (r2.c3 <> r8.c3) AND (r2.c3 <> r9.c3) AND (r2.c4 <> r3.c4) AND (r2.c4 <> r4.c4) AND (r2.c4 <> r5.c4) AND
(r2.c4 <> r6.c4) AND (r2.c4 <> r7.c4) AND (r2.c4 <> r8.c4) AND (r2.c4 <> r9.c4) AND (r2.c5 <> r3.c5) AND (r2.c5 <> r4.c5) AND (r2.c5 <> r5.c5) AND (r2.c5 <> r6.c5) AND (r2.c5 <> r7.c5) AND (r2.c5 <> r8.c5) AND (r2.c5 <> r9.c5) AND (r2.c6 <> r3.c6) AND (r2.c6 <> r4.c6) AND (r2.c6 <> r5.c6) AND (r2.c6 <> r6.c6) AND (r2.c6 <> r7.c6) AND
(r2.c6 <> r8.c6) AND (r2.c6 <> r9.c6) AND (r2.c7 <> r3.c7) AND (r2.c7 <> r4.c7) AND (r2.c7 <> r5.c7) AND (r2.c7 <> r6.c7) AND (r2.c7 <> r7.c7) AND (r2.c7 <> r8.c7) AND (r2.c7 <> r9.c7) AND (r2.c8 <> r3.c8) AND (r2.c8 <> r4.c8) AND (r2.c8 <> r5.c8) AND (r2.c8 <> r6.c8) AND (r2.c8 <> r7.c8) AND (r2.c8 <> r8.c8) AND (r2.c8 <> r9.c8) AND
(r2.c9 <> r3.c9) AND (r2.c9 <> r4.c9) AND (r2.c9 <> r5.c9) AND (r2.c9 <> r6.c9) AND (r2.c9 <> r7.c9) AND (r2.c9 <> r8.c9) AND (r2.c9 <> r9.c9) AND (r3.c1 <> r4.c1) AND (r3.c1 <> r5.c1) AND (r3.c1 <> r6.c1) AND (r3.c1 <> r7.c1) AND (r3.c1 <> r8.c1) AND (r3.c1 <> r9.c1) AND (r3.c2 <> r4.c2) AND (r3.c2 <> r5.c2) AND (r3.c2 <> r6.c2) AND
(r3.c2 <> r7.c2) AND (r3.c2 <> r8.c2) AND (r3.c2 <> r9.c2) AND (r3.c3 <> r4.c3) AND (r3.c3 <> r5.c3) AND (r3.c3 <> r6.c3) AND (r3.c3 <> r7.c3) AND (r3.c3 <> r8.c3) AND (r3.c3 <> r9.c3) AND (r3.c4 <> r4.c4) AND (r3.c4 <> r5.c4) AND (r3.c4 <> r6.c4) AND (r3.c4 <> r7.c4) AND (r3.c4 <> r8.c4) AND (r3.c4 <> r9.c4) AND (r3.c5 <> r4.c5) AND
(r3.c5 <> r5.c5) AND (r3.c5 <> r6.c5) AND (r3.c5 <> r7.c5) AND (r3.c5 <> r8.c5) AND (r3.c5 <> r9.c5) AND (r3.c6 <> r4.c6) AND (r3.c6 <> r5.c6) AND (r3.c6 <> r6.c6) AND (r3.c6 <> r7.c6) AND (r3.c6 <> r8.c6) AND (r3.c6 <> r9.c6) AND (r3.c7 <> r4.c7) AND (r3.c7 <> r5.c7) AND (r3.c7 <> r6.c7) AND (r3.c7 <> r7.c7) AND (r3.c7 <> r8.c7) AND
(r3.c7 <> r9.c7) AND (r3.c8 <> r4.c8) AND (r3.c8 <> r5.c8) AND (r3.c8 <> r6.c8) AND (r3.c8 <> r7.c8) AND (r3.c8 <> r8.c8) AND (r3.c8 <> r9.c8) AND (r3.c9 <> r4.c9) AND (r3.c9 <> r5.c9) AND (r3.c9 <> r6.c9) AND (r3.c9 <> r7.c9) AND (r3.c9 <> r8.c9) AND (r3.c9 <> r9.c9) AND (r4.c1 <> r5.c1) AND (r4.c1 <> r6.c1) AND (r4.c1 <> r7.c1) AND
(r4.c1 <> r8.c1) AND (r4.c1 <> r9.c1) AND (r4.c2 <> r5.c2) AND (r4.c2 <> r6.c2) AND (r4.c2 <> r7.c2) AND (r4.c2 <> r8.c2) AND (r4.c2 <> r9.c2) AND (r4.c3 <> r5.c3) AND (r4.c3 <> r6.c3) AND (r4.c3 <> r7.c3) AND (r4.c3 <> r8.c3) AND (r4.c3 <> r9.c3) AND (r4.c4 <> r5.c4) AND (r4.c4 <> r6.c4) AND (r4.c4 <> r7.c4) AND (r4.c4 <> r8.c4) AND
(r4.c4 <> r9.c4) AND (r4.c5 <> r5.c5) AND (r4.c5 <> r6.c5) AND (r4.c5 <> r7.c5) AND (r4.c5 <> r8.c5) AND (r4.c5 <> r9.c5) AND (r4.c6 <> r5.c6) AND (r4.c6 <> r6.c6) AND (r4.c6 <> r7.c6) AND (r4.c6 <> r8.c6) AND (r4.c6 <> r9.c6) AND (r4.c7 <> r5.c7) AND (r4.c7 <> r6.c7) AND (r4.c7 <> r7.c7) AND (r4.c7 <> r8.c7) AND (r4.c7 <> r9.c7) AND
(r4.c8 <> r5.c8) AND (r4.c8 <> r6.c8) AND (r4.c8 <> r7.c8) AND (r4.c8 <> r8.c8) AND (r4.c8 <> r9.c8) AND (r4.c9 <> r5.c9) AND (r4.c9 <> r6.c9) AND (r4.c9 <> r7.c9) AND (r4.c9 <> r8.c9) AND (r4.c9 <> r9.c9) AND (r5.c1 <> r6.c1) AND (r5.c1 <> r7.c1) AND (r5.c1 <> r8.c1) AND (r5.c1 <> r9.c1) AND (r5.c2 <> r6.c2) AND (r5.c2 <> r7.c2) AND
(r5.c2 <> r8.c2) AND (r5.c2 <> r9.c2) AND (r5.c3 <> r6.c3) AND (r5.c3 <> r7.c3) AND (r5.c3 <> r8.c3) AND (r5.c3 <> r9.c3) AND (r5.c4 <> r6.c4) AND (r5.c4 <> r7.c4) AND (r5.c4 <> r8.c4) AND (r5.c4 <> r9.c4) AND (r5.c5 <> r6.c5) AND (r5.c5 <> r7.c5) AND (r5.c5 <> r8.c5) AND (r5.c5 <> r9.c5) AND (r5.c6 <> r6.c6) AND (r5.c6 <> r7.c6) AND
(r5.c6 <> r8.c6) AND (r5.c6 <> r9.c6) AND (r5.c7 <> r6.c7) AND (r5.c7 <> r7.c7) AND (r5.c7 <> r8.c7) AND (r5.c7 <> r9.c7) AND (r5.c8 <> r6.c8) AND (r5.c8 <> r7.c8) AND (r5.c8 <> r8.c8) AND (r5.c8 <> r9.c8) AND (r5.c9 <> r6.c9) AND (r5.c9 <> r7.c9) AND (r5.c9 <> r8.c9) AND (r5.c9 <> r9.c9) AND (r6.c1 <> r7.c1) AND (r6.c1 <> r8.c1) AND
(r6.c1 <> r9.c1) AND (r6.c2 <> r7.c2) AND (r6.c2 <> r8.c2) AND (r6.c2 <> r9.c2) AND (r6.c3 <> r7.c3) AND (r6.c3 <> r8.c3) AND (r6.c3 <> r9.c3) AND (r6.c4 <> r7.c4) AND (r6.c4 <> r8.c4) AND (r6.c4 <> r9.c4) AND (r6.c5 <> r7.c5) AND (r6.c5 <> r8.c5) AND (r6.c5 <> r9.c5) AND (r6.c6 <> r7.c6) AND (r6.c6 <> r8.c6) AND (r6.c6 <> r9.c6) AND
(r6.c7 <> r7.c7) AND (r6.c7 <> r8.c7) AND (r6.c7 <> r9.c7) AND (r6.c8 <> r7.c8) AND (r6.c8 <> r8.c8) AND (r6.c8 <> r9.c8) AND (r6.c9 <> r7.c9) AND (r6.c9 <> r8.c9) AND (r6.c9 <> r9.c9) AND (r7.c1 <> r8.c1) AND (r7.c1 <> r9.c1) AND (r7.c2 <> r8.c2) AND (r7.c2 <> r9.c2) AND (r7.c3 <> r8.c3) AND (r7.c3 <> r9.c3) AND (r7.c4 <> r8.c4) AND
(r7.c4 <> r9.c4) AND (r7.c5 <> r8.c5) AND (r7.c5 <> r9.c5) AND (r7.c6 <> r8.c6) AND (r7.c6 <> r9.c6) AND (r7.c7 <> r8.c7) AND (r7.c7 <> r9.c7) AND (r7.c8 <> r8.c8) AND (r7.c8 <> r9.c8) AND (r7.c9 <> r8.c9) AND (r7.c9 <> r9.c9) AND (r8.c1 <> r9.c1) AND (r8.c2 <> r9.c2) AND (r8.c3 <> r9.c3) AND (r8.c4 <> r9.c4) AND (r8.c5 <> r9.c5) AND
(r8.c6 <> r9.c6) AND (r8.c7 <> r9.c7) AND (r8.c8 <> r9.c8) AND (r8.c9 <> r9.c9) AND
-- Nombres uniques dans chaque maison de 3x3
(r1.c1 <> r2.c2) AND (r1.c1 <> r2.c3) AND (r1.c1 <> r3.c2) AND (r1.c1 <> r3.c3) AND (r1.c2 <> r2.c1) AND (r1.c2 <> r2.c3) AND (r1.c2 <> r3.c1) AND (r1.c2 <> r3.c3) AND (r1.c3 <> r2.c1) AND (r1.c3 <> r2.c2) AND (r1.c3 <> r3.c1) AND (r1.c3 <> r3.c2) AND (r1.c4 <> r2.c5) AND (r1.c4 <> r2.c6) AND (r1.c4 <> r3.c5) AND (r1.c4 <> r3.c6) AND
(r1.c5 <> r2.c4) AND (r1.c5 <> r2.c6) AND (r1.c5 <> r3.c4) AND (r1.c5 <> r3.c6) AND (r1.c6 <> r2.c4) AND (r1.c6 <> r2.c5) AND (r1.c6 <> r3.c4) AND (r1.c6 <> r3.c5) AND (r1.c7 <> r2.c8) AND (r1.c7 <> r2.c9) AND (r1.c7 <> r3.c8) AND (r1.c7 <> r3.c9) AND (r1.c8 <> r2.c7) AND (r1.c8 <> r2.c9) AND (r1.c8 <> r3.c7) AND (r1.c8 <> r3.c9) AND
(r1.c9 <> r2.c7) AND (r1.c9 <> r2.c8) AND (r1.c9 <> r3.c7) AND (r1.c9 <> r3.c8) AND (r2.c1 <> r3.c2) AND (r2.c1 <> r3.c3) AND (r2.c2 <> r3.c1) AND (r2.c2 <> r3.c3) AND (r2.c3 <> r3.c1) AND (r2.c3 <> r3.c2) AND (r2.c4 <> r3.c5) AND (r2.c4 <> r3.c6) AND (r2.c5 <> r3.c4) AND (r2.c5 <> r3.c6) AND (r2.c6 <> r3.c4) AND (r2.c6 <> r3.c5) AND
(r2.c7 <> r3.c8) AND (r2.c7 <> r3.c9) AND (r2.c8 <> r3.c7) AND (r2.c8 <> r3.c9) AND (r2.c9 <> r3.c7) AND (r2.c9 <> r3.c8) AND (r4.c1 <> r5.c2) AND (r4.c1 <> r5.c3) AND (r4.c1 <> r6.c2) AND (r4.c1 <> r6.c3) AND (r4.c2 <> r5.c1) AND (r4.c2 <> r5.c3) AND (r4.c2 <> r6.c1) AND (r4.c2 <> r6.c3) AND (r4.c3 <> r5.c1) AND (r4.c3 <> r5.c2) AND
(r4.c3 <> r6.c1) AND (r4.c3 <> r6.c2) AND (r4.c4 <> r5.c5) AND (r4.c4 <> r5.c6) AND (r4.c4 <> r6.c5) AND (r4.c4 <> r6.c6) AND (r4.c5 <> r5.c4) AND (r4.c5 <> r5.c6) AND (r4.c5 <> r6.c4) AND (r4.c5 <> r6.c6) AND (r4.c6 <> r5.c4) AND (r4.c6 <> r5.c5) AND (r4.c6 <> r6.c4) AND (r4.c6 <> r6.c5) AND (r4.c7 <> r5.c8) AND (r4.c7 <> r5.c9) AND
(r4.c7 <> r6.c8) AND (r4.c7 <> r6.c9) AND (r4.c8 <> r5.c7) AND (r4.c8 <> r5.c9) AND (r4.c8 <> r6.c7) AND (r4.c8 <> r6.c9) AND (r4.c9 <> r5.c7) AND (r4.c9 <> r5.c8) AND (r4.c9 <> r6.c7) AND (r4.c9 <> r6.c8) AND (r5.c1 <> r6.c2) AND (r5.c1 <> r6.c3) AND (r5.c2 <> r6.c1) AND (r5.c2 <> r6.c3) AND (r5.c3 <> r6.c1) AND (r5.c3 <> r6.c2) AND
(r5.c4 <> r6.c5) AND (r5.c4 <> r6.c6) AND (r5.c5 <> r6.c4) AND (r5.c5 <> r6.c6) AND (r5.c6 <> r6.c4) AND (r5.c6 <> r6.c5) AND (r5.c7 <> r6.c8) AND (r5.c7 <> r6.c9) AND (r5.c8 <> r6.c7) AND (r5.c8 <> r6.c9) AND (r5.c9 <> r6.c7) AND (r5.c9 <> r6.c8) AND (r7.c1 <> r8.c2) AND (r7.c1 <> r8.c3) AND (r7.c1 <> r9.c2) AND (r7.c1 <> r9.c3) AND
(r7.c2 <> r8.c1) AND (r7.c2 <> r8.c3) AND (r7.c2 <> r9.c1) AND (r7.c2 <> r9.c3) AND (r7.c3 <> r8.c1) AND (r7.c3 <> r8.c2) AND (r7.c3 <> r9.c1) AND (r7.c3 <> r9.c2) AND (r7.c4 <> r8.c5) AND (r7.c4 <> r8.c6) AND (r7.c4 <> r9.c5) AND (r7.c4 <> r9.c6) AND (r7.c5 <> r8.c4) AND (r7.c5 <> r8.c6) AND (r7.c5 <> r9.c4) AND (r7.c5 <> r9.c6) AND
(r7.c6 <> r8.c4) AND (r7.c6 <> r8.c5) AND (r7.c6 <> r9.c4) AND (r7.c6 <> r9.c5) AND (r7.c7 <> r8.c8) AND (r7.c7 <> r8.c9) AND (r7.c7 <> r9.c8) AND (r7.c7 <> r9.c9) AND (r7.c8 <> r8.c7) AND (r7.c8 <> r8.c9) AND (r7.c8 <> r9.c7) AND (r7.c8 <> r9.c9) AND (r7.c9 <> r8.c7) AND (r7.c9 <> r8.c8) AND (r7.c9 <> r9.c7) AND (r7.c9 <> r9.c8) AND
(r8.c1 <> r9.c2) AND (r8.c1 <> r9.c3) AND (r8.c2 <> r9.c1) AND (r8.c2 <> r9.c3) AND (r8.c3 <> r9.c1) AND (r8.c3 <> r9.c2) AND (r8.c4 <> r9.c5) AND (r8.c4 <> r9.c6) AND (r8.c5 <> r9.c4) AND (r8.c5 <> r9.c6) AND (r8.c6 <> r9.c4) AND (r8.c6 <> r9.c5) AND (r8.c7 <> r9.c8) AND (r8.c7 <> r9.c9) AND (r8.c8 <> r9.c7) AND (r8.c8 <> r9.c9) AND
(r8.c9 <> r9.c7) AND (r8.c9 <> r9.c8);

Maintenant, nous avons tout ce qu’il faut pour débuter! Si vous avez rencontré des difficultés avec le téléchargement du fichier positions.sql, contactez-moi et je me ferai un plaisir de vous envoyez le fichier compressé (format Gzip) par courriel. Consultez ma page « À propos » pour savoir à quelle adresse courriel me rejoindre!

7. Tester une grille

Asteure que toute la poutine (expression québécoise parfois utilisée pour désigner les tâches cléricales, répétitives, procédurales, techniques ou ennuyantes) est complétée, examinons comment notre solution se comporte pour cette grille :

Pour solutionner la grille, nous devons exécuter cette requête SQL :

SELECT *
FROM sudoku_rows_view
WHERE
(r1c1 = 5) AND (r1c2 = 3) AND (r1c5 = 7) AND (r2c1 = 6) AND
(r2c4 = 1) AND (r2c5 = 9) AND (r2c6 = 5) AND (r3c2 = 9) AND
(r3c3 = 8) AND (r3c8 = 6) AND (r4c1 = 8) AND (r4c5 = 6) AND
(r4c9 = 3) AND (r5c1 = 4) AND (r5c4 = 8) AND (r5c6 = 3) AND
(r5c9 = 1) AND (r6c1 = 7) AND (r6c5 = 2) AND (r6c9 = 6) AND
(r7c2 = 6) AND (r7c7 = 2) AND (r7c8 = 8) AND (r8c4 = 4) AND
(r8c5 = 1) AND (r8c6 = 9) AND (r8c9 = 5) AND (r9c5 = 8) AND
(r9c8 = 7) AND (r9c9 = 9);

Évidemment, je l’espère, vous aurez compris que r8c9 signifie « rangée 8 colonne 9 », etc.

Tada!

Victoire!

Voici ce que le EXPLAIN de la requête a à dire :


mysql> explain
-> SELECT *
-> FROM sudoku_rows_view
-> WHERE
-> (r1c1 = 5) AND (r1c2 = 3) AND (r1c5 = 7) AND (r2c1 = 6) AND
-> (r2c4 = 1) AND (r2c5 = 9) AND (r2c6 = 5) AND (r3c2 = 9) AND
-> (r3c3 = 8) AND (r3c8 = 6) AND (r4c1 = 8) AND (r4c5 = 6) AND
-> (r4c9 = 3) AND (r5c1 = 4) AND (r5c4 = 8) AND (r5c6 = 3) AND
-> (r5c9 = 1) AND (r6c1 = 7) AND (r6c5 = 2) AND (r6c9 = 6) AND
-> (r7c2 = 6) AND (r7c7 = 2) AND (r7c8 = 8) AND (r8c4 = 4) AND
-> (r8c5 = 1) AND (r8c6 = 9) AND (r8c9 = 5) AND (r9c5 = 8) AND
-> (r9c8 = 7) AND (r9c9 = 9);
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+------+------+--------------------------------------------------------------+
| id | select_type | table | type        | possible_keys                                                                                                                                      | key         | key_len | ref  | rows | Extra                                                        |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+------+------+--------------------------------------------------------------+
|  1 | SIMPLE      | r5    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i16,i19,i49 | 2,2,2   | NULL |   68 | Using intersect(i16,i19,i49); Using where                    |
|  1 | SIMPLE      | r2    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i14,i15,i16 | 2,2,2   | NULL |   78 | Using intersect(i14,i15,i16); Using where; Using join buffer |
|  1 | SIMPLE      | r8    | index_merge | i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9                                                                                     | i45,i46,i59 | 2,2,2   | NULL |   78 | Using intersect(i45,i46,i59); Using where; Using join buffer |
|  1 | SIMPLE      | r3    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i28,i38     | 2,2     | NULL |  551 | Using intersect(i28,i38); Using where; Using join buffer     |
|  1 | SIMPLE      | r6    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9                         | i19,i59     | 2,2     | NULL |  551 | Using intersect(i19,i59); Using where; Using join buffer     |
|  1 | SIMPLE      | r1    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i12,i15     | 2,2     | NULL |  624 | Using intersect(i12,i15); Using where; Using join buffer     |
|  1 | SIMPLE      | r9    | index_merge | i56,i57,i58,i59,i89,i9                                                                                                                             | i58,i59     | 2,2     | NULL |  624 | Using intersect(i58,i59); Using where; Using join buffer     |
|  1 | SIMPLE      | r4    | index_merge | i12,i13,i14,i15,i16,i17,i18,i19,i23,i24,i25,i26,i27,i28,i29,i34,i35,i36,i37,i38,i39,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9 | i15,i19     | 2,2     | NULL |  625 | Using intersect(i15,i19); Using where; Using join buffer     |
|  1 | SIMPLE      | r7    | index_merge | i23,i24,i25,i26,i27,i28,i29,i45,i46,i47,i48,i49,i56,i57,i58,i59,i67,i68,i69,i78,i79,i89,i9                                                         | i27,i28     | 2,2     | NULL |  625 | Using intersect(i27,i28); Using where; Using join buffer     |
+----+-------------+-------+-------------+----------------------------------------------------------------------------------------------------------------------------------------------------+-------------+---------+------+------+--------------------------------------------------------------+
9 rows in set (0.06 sec)

Voilà!

Tout fonctionne à merveille! Seulement 0.39 secondes pour solutionner la grille!  Savourons le résultat :


mysql> SELECT *
-> FROM sudoku_rows_view
-> WHERE
-> (r1c1 = 5) AND (r1c2 = 3) AND (r1c5 = 7) AND (r2c1 = 6) AND
-> (r2c4 = 1) AND (r2c5 = 9) AND (r2c6 = 5) AND (r3c2 = 9) AND
-> (r3c3 = 8) AND (r3c8 = 6) AND (r4c1 = 8) AND (r4c5 = 6) AND
-> (r4c9 = 3) AND (r5c1 = 4) AND (r5c4 = 8) AND (r5c6 = 3) AND
-> (r5c9 = 1) AND (r6c1 = 7) AND (r6c5 = 2) AND (r6c9 = 6) AND
-> (r7c2 = 6) AND (r7c7 = 2) AND (r7c8 = 8) AND (r8c4 = 4) AND
-> (r8c5 = 1) AND (r8c6 = 9) AND (r8c9 = 5) AND (r9c5 = 8) AND
-> (r9c8 = 7) AND (r9c9 = 9);
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
| r1c1 | r1c2 | r1c3 | r1c4 | r1c5 | r1c6 | r1c7 | r1c8 | r1c9 | r2c1 | r2c2 | r2c3 | r2c4 | r2c5 | r2c6 | r2c7 | r2c8 | r2c9 | r3c1 | r3c2 | r3c3 | r3c4 | r3c5 | r3c6 | r3c7 | r3c8 | r3c9 | r4c1 | r4c2 | r4c3 | r4c4 | r4c5 | r4c6 | r4c7 | r4c8 | r4c9 | r5c1 | r5c2 | r5c3 | r5c4 | r5c5 | r5c6 | r5c7 | r5c8 | r5c9 | r6c1 | r6c2 | r6c3 | r6c4 | r6c5 | r6c6 | r6c7 | r6c8 | r6c9 | r7c1 | r7c2 | r7c3 | r7c4 | r7c5 | r7c6 | r7c7 | r7c8 | r7c9 | r8c1 | r8c2 | r8c3 | r8c4 | r8c5 | r8c6 | r8c7 | r8c8 | r8c9 | r9c1 | r9c2 | r9c3 | r9c4 | r9c5 | r9c6 | r9c7 | r9c8 | r9c9 |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
|    5 |    3 |    4 |    6 |    7 |    8 |    9 |    1 |    2 |    6 |    7 |    2 |    1 |    9 |    5 |    3 |    4 |    8 |    1 |    9 |    8 |    3 |    4 |    2 |    5 |    6 |    7 |    8 |    5 |    9 |    7 |    6 |    1 |    4 |    2 |    3 |    4 |    2 |    6 |    8 |    5 |    3 |    7 |    9 |    1 |    7 |    1 |    3 |    9 |    2 |    4 |    8 |    5 |    6 |    9 |    6 |    1 |    5 |    3 |    7 |    2 |    8 |    4 |    2 |    8 |    7 |    4 |    1 |    9 |    6 |    3 |    5 |    3 |    4 |    5 |    2 |    8 |    6 |    1 |    7 |    9 |
+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+
1 row in set (0.39 sec)

Trop facile ? Hmmmm!?!? Peut-être!  À moins que…

C’était beaucoup trop beau! Comme nous le verrons au prochain article, plusieurs problèmes pointent à l’horizon (et espérons-le, plusieurs remèdes!) et nous devrons faire beaucoup mieux et plus vite avec les outils que nous avons pour arriver à résoudre certaines grilles très particulières.

En attendant la seconde partie de cet article, amusez-vous bien et expérimentez !

Note: j’ai déjà publié cet article en anglais sur mes autres blogues dont récemment ici (l’autre blogue est disparu depuis longtemps). Ne vous en faites pas, il ne s’agit pas d’un cas de plagiat!!!

Prochaine étape, chers lecteurs, nous apprendrons à presser un citron et à en extraire tout le jus!