Derniers messages sur Zeste de Savoirhttps://zestedesavoir.com/forums/2018-07-12T23:18:44+02:00Les derniers messages parus sur le forum de Zeste de Savoir.Critère SQL pour vérifier une "continuité" de plusieurs éléments dans le temps, message #1836792018-07-12T23:18:44+02:00Ymox/@Ymoxhttps://zestedesavoir.com/forums/sujet/10941/critere-sql-pour-verifier-une-continuite-de-plusieurs-elements-dans-le-temps/?page=1#p183679<p>Je ne souhaite pas laisser ce sujet en plan, donc je réponds.</p>
<p>Mais c’est pour dire que je n’ai pas réussi à adapter la requête, et que le système que j’avais imaginé n’est malheureusement pas viable. Du coup, cette manière de détecter n’est plus d’actualité.</p>
<p>Encore merci pour vos propositions.</p>Critère SQL pour vérifier une "continuité" de plusieurs éléments dans le temps, message #1832262018-07-06T10:54:38+02:00Ymox/@Ymoxhttps://zestedesavoir.com/forums/sujet/10941/critere-sql-pour-verifier-une-continuite-de-plusieurs-elements-dans-le-temps/?page=1#p183226<p>Mince, je pensais que SQL Fiddle permettait de naviguer entre les différentes requêtes testées avec le schéma… Bon, j’imagine assez que vous n’en avez pas besoin, mais il suffirait d’ajouter <code>/{numéro d'essai}</code> (à partir de 1) à l’URL fourni plus haut pour voir ce qui a été essayé.</p>
<blockquote>
<p>Tu travailles sur des jours ; je vais considérer que ce sont des entiers ; il peut y avoir une petite embrouille sur ce point.</p>
<p>Une des difficultés, c’est qu’on travaille sur des intervalles. Si jour_début = jour_fin, alors la durée n’est pas 0, mais 1 jour. Et donc pour le cas général, la durée d’un élément n’est pas fin_element-debut_element, mais fin_element-debut_element+1</p>
</blockquote>
<p>Désolé, c’est vrai que j’utilise la dénomination telle qu’exprimée dans le besoin, alors qu’on compte en réalité les nuits (d’ailleurs, je suis assez certain que ça va me retomber dessus à un moment ou un autre juste parce que ce ne sera pas clair pour l’utilisateur final…).<br>
Mais du coup, ça implique que les dates de début et de fin des éléments doivent être les mêmes, je n’ai pas besoin d’ajouter ce <code>+ 1</code> qui serait effectivement nécessaire en cas de décompte des jours.</p>
<p>Je vais tenter de m’approprier vos propositions (notamment les adapter à MySQL 5.6 puis voir comment les envoyer dans le DQL de Doctrine) et je reviendrai éditer pour la suite.</p>
<p>Merci de votre aide</p>
<hr>
<h4>Edit</h4>
<p>Malheureusement, je ne vois pas trop comment adapter <code>OVER(ORDER BY …)</code> pour MySQL (je me méfie que ça implique plus que de simplement ordonner sur toute la requête), je vais donc voir avec la proposition de elegance.</p>Critère SQL pour vérifier une "continuité" de plusieurs éléments dans le temps, message #1831822018-07-05T21:09:55+02:00elegance/@elegancehttps://zestedesavoir.com/forums/sujet/10941/critere-sql-pour-verifier-une-continuite-de-plusieurs-elements-dans-le-temps/?page=1#p183182<p>Tu travailles sur des jours ; je vais considérer que ce sont des entiers ; il peut y avoir une petite embrouille sur ce point.</p>
<p>Une des difficultés, c’est qu’on travaille sur des intervalles. Si jour_début = jour_fin, alors la durée n’est pas 0, mais 1 jour. Et donc pour le cas général, la durée d’un élément n’est pas fin_element-debut_element, mais fin_element-debut_element+1</p>
<p>Allons-y progressivement ; il faut dtoujours décomposer un problème compliqué en problèmes plus simples.</p>
<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42</pre></div></td><td class="code"><div class="codehilite"><pre><span></span><span class="k">select</span> <span class="n">id_personne</span> <span class="p">,</span> <span class="k">min</span><span class="p">(</span><span class="n">debut_element</span><span class="p">)</span> <span class="k">as</span> <span class="n">min_jour</span> <span class="p">,</span> <span class="k">max</span><span class="p">(</span><span class="n">fin_element</span><span class="p">)</span> <span class="k">as</span> <span class="n">max_jour</span>
<span class="k">from</span> <span class="n">ma_table</span>
<span class="k">group</span> <span class="k">by</span> <span class="n">id_personne</span>
<span class="c1">-- Cette requete donne le min(debut_element) et max(fin_element) pour chaque personne.</span>
<span class="k">select</span> <span class="n">id_personne</span>
<span class="k">from</span> <span class="n">ma_table</span>
<span class="k">group</span> <span class="k">by</span> <span class="n">id_personne</span><span class="p">,</span> <span class="n">debut</span><span class="p">,</span> <span class="n">fin</span>
<span class="k">having</span> <span class="k">min</span><span class="p">(</span><span class="n">debut_element</span><span class="p">)</span> <span class="o">=</span> <span class="n">debut</span> <span class="k">and</span> <span class="k">max</span><span class="p">(</span><span class="n">fin_element</span><span class="p">)</span> <span class="o">=</span> <span class="n">fin</span>
<span class="c1">-- Cette 2ème requete donne les individus pour lesquels le debut et la fin matchent </span>
<span class="c1">-- entre les colonne 'Debut/fin' et les colonnes éléments.</span>
<span class="c1">-- Pas tout à fait sur que cette condition t'intéresse.</span>
<span class="k">select</span> <span class="n">id_personne</span>
<span class="k">from</span> <span class="n">ma_table</span>
<span class="k">group</span> <span class="k">by</span> <span class="n">id_personne</span>
<span class="k">having</span> <span class="k">max</span><span class="p">(</span><span class="n">fin_element</span><span class="p">)</span> <span class="o">-</span> <span class="k">min</span><span class="p">(</span><span class="n">debut_element</span><span class="p">)</span><span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="k">sum</span> <span class="p">(</span> <span class="n">fin_element</span> <span class="o">-</span> <span class="n">debut_element</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="c1">-- Cette requete donne les personnes pour lesquelles la somme des durées cumulées des 'éléments' </span>
<span class="c1">-- coïncide avec la durée totale max_fin - min_debut +1</span>
<span class="c1">--</span>
<span class="c1">-- La somme des longueurs des maillons coïncide avec la longueur de la chaine.</span>
<span class="c1">-- Condition nécessaire pour que nos éléments forment une "chaine" , mais condition non suffisante.</span>
<span class="k">select</span> <span class="n">id_personne</span>
<span class="k">from</span> <span class="n">ma_table</span>
<span class="k">group</span> <span class="k">by</span> <span class="n">id_personne</span>
<span class="k">having</span> <span class="k">max</span><span class="p">(</span><span class="n">fin_element</span><span class="p">)</span> <span class="o">-</span> <span class="k">min</span><span class="p">(</span><span class="n">debut_element</span><span class="p">)</span><span class="o">+</span> <span class="mi">1</span> <span class="o">=</span> <span class="k">sum</span> <span class="p">(</span> <span class="n">fin_element</span> <span class="o">-</span> <span class="n">debut_element</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="n">MINUS</span>
<span class="k">select</span> <span class="n">id_personne</span> <span class="k">from</span> <span class="n">ma_table</span> <span class="n">t</span>
<span class="k">where</span> <span class="n">not_exists</span>
<span class="p">(</span> <span class="k">select</span> <span class="o">*</span> <span class="k">from</span> <span class="n">ma_table</span> <span class="n">t1</span><span class="p">,</span> <span class="n">ma_table</span> <span class="n">t2</span>
<span class="k">where</span> <span class="n">t1</span><span class="p">.</span><span class="n">id_personne</span> <span class="o">=</span> <span class="n">t</span><span class="p">.</span><span class="n">id_personne</span> <span class="k">and</span> <span class="n">t2</span><span class="p">.</span><span class="n">id_personne</span> <span class="o">=</span> <span class="n">t</span><span class="p">.</span><span class="n">id_personne</span>
<span class="k">and</span> <span class="n">t1</span><span class="p">.</span><span class="n">rowid</span> <span class="o"><></span><span class="n">t2</span><span class="p">.</span><span class="n">rowid</span> <span class="k">and</span> <span class="n">t1</span><span class="p">.</span><span class="n">fin_element</span> <span class="k">between</span> <span class="n">t2</span><span class="p">.</span><span class="n">debut_element</span> <span class="k">and</span> <span class="n">t2</span><span class="p">.</span><span class="n">fin_element</span> <span class="p">)</span>
<span class="c1">-- Cette dernière requete, c'est la requête précédente </span>
<span class="c1">-- MINUS</span>
<span class="c1">-- la liste des personnes pour lesquelles on a 2 éléments qui se chevauchent.</span>
<span class="o">`</span>
</pre></div>
</td></tr></table></div>
<p>A priori la dernière requête est celle qu’il te faut. Il faut peut-être combiner avec la condition  : having min(debut_element) = debut and max(fin_element) = fin</p>Critère SQL pour vérifier une "continuité" de plusieurs éléments dans le temps, message #1831662018-07-05T19:14:05+02:00Zérotisme/@Z%C3%A9rotismehttps://zestedesavoir.com/forums/sujet/10941/critere-sql-pour-verifier-une-continuite-de-plusieurs-elements-dans-le-temps/?page=1#p183166<div><table class="codehilitetable"><tr><td class="linenos"><div class="linenodiv"><pre>1
2
3
4
5
6</pre></div></td><td class="code"><div class="codehilite"><pre><span></span> <span class="k">SELECT</span> <span class="n">something</span> <span class="k">FROM</span> <span class="p">(</span>
<span class="k">SELECT</span>
<span class="p">[</span><span class="n">Debut</span><span class="p">]</span>
<span class="p">,[</span><span class="n">Fin</span><span class="p">]</span>
<span class="p">,</span><span class="n">diff</span> <span class="o">=</span> <span class="n">DATEDIFF</span><span class="p">(</span><span class="n">hour</span><span class="p">,</span> <span class="n">Lag</span><span class="p">([</span><span class="n">Fin</span><span class="p">],</span> <span class="mi">1</span><span class="p">)</span> <span class="n">OVER</span><span class="p">(</span><span class="k">ORDER</span> <span class="k">BY</span> <span class="p">[</span><span class="n">Debut</span><span class="p">],</span> <span class="p">[</span><span class="n">Fin</span><span class="p">]),</span> <span class="p">[</span><span class="n">Debut</span><span class="p">])</span>
<span class="k">WHERE</span> <span class="n">something</span><span class="p">.</span><span class="n">diff</span> <span class="o">></span> <span class="mi">24</span>
</pre></div>
</td></tr></table></div>
<p>J’ai du developper quelque chose de semblable ( pour recuperer des "timepunch" de travail qui ont moins de 8hr d’ecart entre le OUT et le prochain IN ). C’est plutot "pseudocode" mais ca ressemble a ce que tu aurais besoin.</p>Critère SQL pour vérifier une "continuité" de plusieurs éléments dans le temps, message #1831262018-07-05T09:15:42+02:00Ymox/@Ymoxhttps://zestedesavoir.com/forums/sujet/10941/critere-sql-pour-verifier-une-continuite-de-plusieurs-elements-dans-le-temps/?page=1#p183126<figure>
<blockquote>
<p>Tu dis par exemple : ’ L’idée est donc de sortir soit Pierre, pour qui : ’ ; je lis cela et je me pose une question. Est-ce que sortir, ça veut dire Exclure, ou au contraire, ça veut dire afficher, parce que justement, c’est ça la solution.</p>
</blockquote>
<figcaption><a href="#p183097">elegance</a></figcaption>
</figure>
<p>En fait, il y a les deux cas : soit je n’affiche pas Pierre parce que je souhaite afficher ceux pour qui les différents critères listés ne sont pas remplis, soit je l’affiche parce que justement les critères sont remplis.</p>
<figure>
<blockquote>
<p>Tu dis aussi (première ligne) que tu veux Vérifier … Vérifier, ça veut dire que ta fonction va renvoyer Oui ou non. Point final.</p>
</blockquote>
<figcaption><a href="#p183097">elegance</a></figcaption>
</figure>
<p>Justement, mon souci est la rédaction de ce critère pour savoir si les éléments sont bien contigus/continus dans le temps. Après, pour ce qui est de savoir s’il retourne oui ou non, je crois que je devrais m’en sortir. Pour rappel :</p>
<figure>
<blockquote>
<p>Ma prise de tête du moment consiste à tenter d’effectuer des requêtes pour vérifier que différents éléments (ayant une date de de début et une de fin), mis dans l’ordre chronologique, forment une suite continue de jours, afin de vérifier que cette suite couvre bien une certaine période. Ces éléments sont liés à des personnes, et je dois donc retourner les personnes selon ce critère de continuité.</p>
<p>[…]</p>
<p>Ce qui me manque actuellement, c’est cette histoire de comparaison entre deux éléments […]</p>
</blockquote>
<figcaption><a href="#p183068">Ymox</a></figcaption>
</figure>
<p>Pour être donc plus précis, c’est <strong>comment rédiger une expression SQL qui permet de savoir que deux enregistrements (ou plus) sont contigus en fonction de leurs dates de début et de fin</strong> qui me pose problème.<br>
Pour être tout à fait honnête, je ne pense pas que je doive parler d’expression au sens MySQL, parce que ce que je cherche à faire n’est peut-être pas le simple fruit d’un truc logique, ça implique probablement des jointures aussi. Donc pour moi ce sera un critère.</p>
<figure>
<blockquote>
<p>Et plus loin, il semblerait que ta fonction ne doive par renvoyer oui ou non, mais renvoyer une extraction de la base, qui vérifie certains critères. Il semblerait, je n’en suis pas sûr.</p>
<p>Je pense qu’en faisant l’effort de formuler précisément quel est ton objectif, quelles sont tes contraintes, tu vas avoir quelque chose de compréhensible par un lecteur lambda. Et donc, tu auras résolu toi-même ton problème.</p>
</blockquote>
<figcaption><a href="#p183097">elegance</a></figcaption>
</figure>
<p>D’accord, la prochaine fois je ne mettrai aucun contexte et je résoudrai le problème avant d’accepter que j’ai besoin d’aide et d’en demander.</p>
<p><strong>Non</strong> c’est pas clair, mais on ne peut pas me reprocher de ne pas avoir expliqué, il me semble.<br>
<strong>Oui</strong> c’est entre autres aussi parce que ce n’est pas clair pour moi que j’ai créé le sujet — et c’est aussi grâce à la réflexion pour le rédiger que j’ai pu formuler les parties "mathématiques" de mes critères énoncés dans le premier message.</p>
<p>Pour le coup, j’aurais grandement mieux apprécié des vraies questions pour que je puisse tenter de mieux expliquer — ce que je ferais volontiers, comme je l’ai dit plus haut, c’est aussi en partie pour m’aider à clarifier que je viens ici, et j’en veux pour preuve que j’ai tenté de répondre à tes interrogations — que ces phrases que <strong><em>JE</em></strong> trouve plutôt lapidaires.</p>
<p>Merci.</p>
<hr>
<h4>Edit</h4>
<p>Le souci pourrait être formulé aussi de la manière suivante.</p>
<div class="question ico-after">
<p>Dans une période, comment savoir si certains jours ne sont pas couverts par au moins une période plus petite ?<br>
<em>ou</em><br>
Comment savoir si les trous entre de petites périodes sont compris dans une plus grande ?</p>
</div>
<p>Je ne peux évidemment pas simplement utiliser <code>BETWEEN</code>, parce que justement cela ne va pas faire de cas des "trous" entre mes dates "globales" et les valeurs des éléments. D’autre part, comme le but est de chercher parmi des personnes, je n’ai pas les dates "globales" de disponible avant de lancer la requête.</p>
<p>Avec ces deux formulations, je me rends compte que mon problème serait de <strong>"calculer ces trous" entre les éléments</strong>.</p>
<hr>
<h4>Edit <sub>2</sub></h4>
<p>Pour les <del>musiciens</del> intéressés, j’ai fait un peu mumuse avec <a href="http://sqlfiddle.com/#!9/8f4b43">un <em>fiddle</em></a>. Il y a plus ou moins les données fournies dans le premier message, la différence étant que j’ai mis trois éléments par personne.</p>Critère SQL pour vérifier une "continuité" de plusieurs éléments dans le temps, message #1830972018-07-04T18:24:41+02:00elegance/@elegancehttps://zestedesavoir.com/forums/sujet/10941/critere-sql-pour-verifier-une-continuite-de-plusieurs-elements-dans-le-temps/?page=1#p183097<p>Je pense qu’il faut que tu fasses un effort pour reformuler ta question.</p>
<p>Tu dis par exemple : ’ L’idée est donc de sortir soit Pierre, pour qui : ’ ; je lis cela et je me pose une question. Est-ce que sortir, ça veut dire Exclure, ou au contraire, ça veut dire afficher, parce que justement, c’est ça la solution.</p>
<p>Tu dis aussi (première ligne) que tu veux Vérifier … Vérifier, ça veut dire que ta fonction va renvoyer Oui ou non. Point final.</p>
<p>Et plus loin, il semblerait que ta fonction ne doive par renvoyer oui ou non, mais renvoyer une extraction de la base, qui vérifie certains critères. Il semblerait, je n’en suis pas sûr.</p>
<p>Je pense qu’en faisant l’effort de formuler précisément quel est ton objectif, quelles sont tes contraintes, tu vas avoir quelque chose de compréhensible par un lecteur lambda. Et donc, tu auras résolu toi-même ton problème.</p>Critère SQL pour vérifier une "continuité" de plusieurs éléments dans le temps, message #1830682018-07-04T15:19:54+02:00Ymox/@Ymoxhttps://zestedesavoir.com/forums/sujet/10941/critere-sql-pour-verifier-une-continuite-de-plusieurs-elements-dans-le-temps/?page=1#p183068<p>Bonjour à tous !</p>
<p>Ma prise de tête du moment consiste à tenter d’effectuer des requêtes pour vérifier que différents éléments (ayant une date de de début et une de fin), mis dans l’ordre chronologique, forment une suite continue de jours, afin de vérifier que cette suite couvre bien une certaine période. Ces éléments sont liés à des personnes, et je dois donc retourner les personnes selon ce critère de continuité.<br>
Il y a évidemment d’autres critères pour sélectionner ces périodes (des statuts), mais je pense que je devrais arriver à les insérer dans la version finale.</p>
<p>Pour exemple, mettons que j’ai des données similaires à celles dans le tableau ci-dessous.</p>
<figure>
<div class="table-wrapper">
<table>
<thead>
<tr>
<th colspan="1" rowspan="1">
<p>Personne</p>
</th>
<th colspan="1" rowspan="1">
<p>Début</p>
</th>
<th colspan="1" rowspan="1">
<p>Fin</p>
</th>
<th colspan="1" rowspan="1">
<p>Début d’élément</p>
</th>
<th colspan="1" rowspan="1">
<p>Fin d’élément</p>
</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="1" rowspan="2">
<p>Pierre</p>
</td>
<td colspan="1" rowspan="2">
<p>2018-10-16</p>
</td>
<td colspan="1" rowspan="2">
<p>2018-10-26</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-16</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-18</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p>2018-10-18</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-26</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="2">
<p>Paul</p>
</td>
<td colspan="1" rowspan="2">
<p>2018-10-16</p>
</td>
<td colspan="1" rowspan="2">
<p>2018-10-26</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-17</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-18</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p>2018-10-18</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-26</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="2">
<p>Marie</p>
</td>
<td colspan="1" rowspan="2">
<p>2018-10-17</p>
</td>
<td colspan="1" rowspan="2">
<p>2018-10-26</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-17</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-18</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p>2018-10-18</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-24</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="2">
<p>Alice</p>
</td>
<td colspan="1" rowspan="2">
<p>2018-10-16</p>
</td>
<td colspan="1" rowspan="2">
<p>2018-10-26</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-16</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-18</p>
</td>
</tr>
<tr>
<td colspan="1" rowspan="1">
<p>2018-10-20</p>
</td>
<td colspan="1" rowspan="1">
<p>2018-10-26</p>
</td>
</tr>
</tbody>
</table>
</div>
<figcaption>Quelques données d’exemple</figcaption>
</figure>
<p>L’idée est donc de sortir soit Pierre, pour qui :</p>
<ul>
<li>la date de début est plus grande ou égale à la date de début du premier élément ;</li>
<li>la date de fin est plus petite ou égale la date de fin du dernier élément ;</li>
<li>la date de fin d’un élément coïncide avec (ou est plus grande que) celle de début d’un autre élément.</li>
</ul>
<p>Ou à l’inverse, sortir Paul, Marie ou Alice :</p>
<ul>
<li>soit parce que la date de début est plus petite que la date de début de tous ses éléments ;</li>
<li>soit parce que la date de fin est plus grande que la date de fin de tous ses éléments ;</li>
<li>soit parce que la période couverte par tous les éléments n’est pas <em>continue</em>, typiquement :<ul>
<li>un des éléments a sa date de fin qui :<ul>
<li>est plus petite que la fin "globale" ;</li>
<li>ne coïncide avec aucune date de début d’un autre élément.</li>
</ul>
</li>
<li>un des éléments a sa date de début qui :<ul>
<li>est plus grande que le début "global" ;</li>
<li>ne coïncide avec aucune date de fin d’un autre élément.</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Je pense que je peux m’en sortir avec pas mal de ces critères :</p>
<ul>
<li>pour savoir si on a au moins un élément qui commence à (ou avant) la date de début globale, une jointure depuis ma personne vers les éléments, jointure avec un "critère renforcé" et la vérification ;</li>
<li>similairement pour voir si on a un élément qui s’arrête à (ou après) la date de fin globale.</li>
</ul>
<p>Ce qui me manque actuellement, c’est cette histoire de comparaison entre deux éléments — dans le cas de Pierre comme dans l’autre — sachant que, histoire de ne pas faire simple, je peux avoir des éléments qui se chevauchent (si on prend le cas de Pierre, la date de fin du premier élément serait le 20, et Pierre répondrait toujours aux critères de "continuité"), et que je n’ai évidemment pas toujours deux éléments ?</p>
<p>Merci d’avance <img alt=":)" src="/static/smileys/smile.png"></p>Requête résultante avec clauses JOIN vides, message #1161122016-06-28T17:40:58+02:00Ymox/@Ymoxhttps://zestedesavoir.com/forums/sujet/6427/requete-resultante-avec-clauses-join-vides/?page=1#p116112<p>Bonjour !</p>
<p>Aujourd’hui, j’ai un petit truc particulier dans un projet qui utilise Doctrine <em>hors Symfony</em> — dans le CMS Concrete5.</p>
<p>Mes entités sont dans un package Concrete5, ce qui fait que quand je l’installe, les tables correspondantes sont automatiquement créés. Mais cela ne valide apparemment pas totalement les classes. Et comme les mappings sont apparemment acceptés que par annotations et que je n’en ai pas trop l’habitude, j’ai peut-être loupé un truc.</p>
<p>Le souci survient quand je tente de récupérer une entité en utilisant un QueryBuilder personnalisé, avec toute une série de jointures — je récupère l’objet principal, des objets liés par une "OneToManyToOne", et des objets enfants de l’objet principal, avec les mêmes types d’objets liés. Là où je ne comprends pas, c’est que l’erreur qui m’est retournée est au niveau de la syntaxe de la requête SQL résultante : les jointures sur une des tables se présentent sous la forme <code>… LEFT JOIN ON LEFT JOIN …</code>, donc aucune table de spécifiée, ni aucune clause de liaison. Doctrine ne râle pas parce que la relation n’existe pas, donc ça semble être bon, mais…</p>
<p>J’ai tenté de supprimer tous les caches que j’avais sous le pointeur (ce qui m’a permis de régler déjà des trucs liés au pseudo-PSR-4 de Concrete5), j’ai activé un mode qui fait que Doctrine me re-génère les <em>proxies</em> à la volée, mais apparemment sans grande chance.</p>
<p>Est-ce que ça a déjà fait le coup à quelqu’un ?</p>
<p>Je fournis mon code, à tout hasard — les trois entités concernées et le repository où se trouve le QueryBuilder qui me serait nécessaire.</p>
<p>Merci d’avance <img src="/static/smileys/smile.png" alt=":)" class="smiley"></p>
<div class="custom-block custom-block-spoiler"><div class="custom-block-body"><div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-php"><span class="hljs-meta"><?php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">Concrete</span>\<span class="hljs-title">Package</span>\<span class="hljs-title">EShop</span>\<span class="hljs-title">Src</span>\<span class="hljs-title">Entity</span>;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Entity</span>(repositoryClass="\Concrete\Package\EShop\Src\Repository\ProductRepository")
* <span class="hljs-doctag">@Table</span>(name="eshop_product")
*/</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>
</span>{
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Id</span>
* <span class="hljs-doctag">@Column</span>(type="integer")
* <span class="hljs-doctag">@GeneratedValue</span>
*/</span>
<span class="hljs-keyword">private</span> $id;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Column</span>(type="string")
* <span class="hljs-doctag">@var</span> string
*/</span>
<span class="hljs-keyword">private</span> $name;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Column</span>(type="string")
* <span class="hljs-doctag">@var</span> string
*/</span>
<span class="hljs-keyword">private</span> $slug;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Column</span>(type="integer")
* <span class="hljs-doctag">@var</span> integer
*/</span>
<span class="hljs-keyword">private</span> $quantity;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Column</span>(type="decimal", precision=6, scale=2)
* <span class="hljs-doctag">@var</span> string
*/</span>
<span class="hljs-keyword">private</span> $price;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Column</span>(type="text", nullable=true)
* <span class="hljs-doctag">@var</span> text
*/</span>
<span class="hljs-keyword">private</span> $description;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@ManyToOne</span>(targetEntity="Product", inversedBy="articles")
* <span class="hljs-doctag">@JoinColumn</span>(name="product_id", referencedColumnName="id", nullable=true)
* <span class="hljs-doctag">@var</span> Product
*/</span>
<span class="hljs-keyword">private</span> $product;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@OneToMany</span>(targetEntity="Product", mappedBy="product")
* <span class="hljs-doctag">@var</span> \Doctrine\Common\Collections\ArrayCollection
*/</span>
<span class="hljs-keyword">private</span> $articles;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@ManyToMany</span>(targetEntity="\Concrete\Package\EShop\Src\Entity\Feature", mappedBy="product")
* <span class="hljs-doctag">@JoinTable</span>(name="article_feature")
* <span class="hljs-doctag">@var</span> \Doctrine\Common\Collections\ArrayCollection
*/</span>
<span class="hljs-keyword">private</span> $features;
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-params">()</span>
</span>{
<span class="hljs-keyword">$this</span>->articles = <span class="hljs-keyword">new</span> \Doctrine\Common\Collections\ArrayCollection();
<span class="hljs-keyword">$this</span>->features = <span class="hljs-keyword">new</span> \Doctrine\Common\Collections\ArrayCollection();
}
<span class="hljs-comment">// …</span>
}
</code></pre></div></div></div>
<div class="custom-block custom-block-spoiler"><div class="custom-block-body"><div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-php"><span class="hljs-meta"><?php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">Concrete</span>\<span class="hljs-title">Package</span>\<span class="hljs-title">EShop</span>\<span class="hljs-title">Src</span>\<span class="hljs-title">Entity</span>;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Entity</span>
* <span class="hljs-doctag">@Table</span>(name="eshop_feature")
*/</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Feature</span>
</span>{
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Id</span>
* <span class="hljs-doctag">@Column</span>(type="bigint")
* <span class="hljs-doctag">@GeneratedValue</span>
* <span class="hljs-doctag">@var</span> bigint
*/</span>
<span class="hljs-keyword">private</span> $id;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Column</span>(type="text", name="`value`")
* <span class="hljs-doctag">@var</span> string
*/</span>
<span class="hljs-keyword">private</span> $value;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@ManyToMany</span>(targetEntity="\Concrete\Package\EShop\Src\Entity\Product", inversedBy="features")
* <span class="hljs-doctag">@var</span> \Doctrine\Common\Collections\ArrayCollection
*/</span>
<span class="hljs-keyword">private</span> $products;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@ManyToOne</span>(targetEntity="\Concrete\Package\EShop\Src\Entity\Property", inversedBy="values")
* <span class="hljs-doctag">@JoinColumn</span>(nullable=false)
* <span class="hljs-doctag">@var</span> \Concrete\Package\EShop\Src\Entity\Property
*/</span>
<span class="hljs-keyword">private</span> $property;
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-params">()</span>
</span>{
<span class="hljs-keyword">$this</span>->products = <span class="hljs-keyword">new</span> \Doctrine\Common\Collections\ArrayCollection();
}
<span class="hljs-comment">// …</span>
}
</code></pre></div></div></div>
<div class="custom-block custom-block-spoiler"><div class="custom-block-body"><div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-php"><span class="hljs-meta"><?php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">Concrete</span>\<span class="hljs-title">Package</span>\<span class="hljs-title">EShop</span>\<span class="hljs-title">Src</span>\<span class="hljs-title">Entity</span>;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Entity</span>
* <span class="hljs-doctag">@Table</span>(name="eshop_property")
*/</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Property</span>
</span>{
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Id</span>
* <span class="hljs-doctag">@Column</span>(type="integer")
* <span class="hljs-doctag">@GeneratedValue</span>
* <span class="hljs-doctag">@var</span> integer
*/</span>
<span class="hljs-keyword">private</span> $id;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@Column</span>(type="string")
* <span class="hljs-doctag">@var</span> string
*/</span>
<span class="hljs-keyword">private</span> $name;
<span class="hljs-comment">/**
* <span class="hljs-doctag">@OneToMany</span>(targetEntity="Feature", mappedBy="property")
* <span class="hljs-doctag">@var</span> \Doctrine\Common\Collections\ArrayCollection
*/</span>
<span class="hljs-keyword">private</span> $values;
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">__construct</span><span class="hljs-params">()</span>
</span>{
<span class="hljs-keyword">$this</span>->values = <span class="hljs-keyword">new</span> \Doctrine\Common\Collections\ArrayCollection();
}
<span class="hljs-comment">// …</span>
}
</code></pre></div></div></div>
<div class="custom-block custom-block-spoiler"><div class="custom-block-body"><div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-php"><span class="hljs-meta"><?php</span>
<span class="hljs-keyword">namespace</span> <span class="hljs-title">Concrete</span>\<span class="hljs-title">Package</span>\<span class="hljs-title">EShop</span>\<span class="hljs-title">Src</span>\<span class="hljs-title">Repository</span>;
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductRepository</span> <span class="hljs-keyword">extends</span> \<span class="hljs-title">Doctrine</span>\<span class="hljs-title">ORM</span>\<span class="hljs-title">EntityRepository</span>
</span>{
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">findAll</span><span class="hljs-params">()</span>
</span>{
$qb = <span class="hljs-keyword">$this</span>->getQueryBuilderFindAll();
<span class="hljs-keyword">return</span> $qb->getQuery()->getResult();
}
<span class="hljs-keyword">public</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getQueryBuilderFindAll</span><span class="hljs-params">()</span>
</span>{
$qb = <span class="hljs-keyword">$this</span>->createQueryBuilder(<span class="hljs-string">'p'</span>);
$qb ->leftJoin(<span class="hljs-string">'p.features'</span>, <span class="hljs-string">'f'</span>)->addSelect(<span class="hljs-string">'f'</span>)
->leftJoin(<span class="hljs-string">'f.property'</span>, <span class="hljs-string">'pr'</span>)->addSelect(<span class="hljs-string">'pr'</span>)
->leftJoin(<span class="hljs-string">'p.articles'</span>, <span class="hljs-string">'a'</span>)->addSelect(<span class="hljs-string">'a'</span>)
->leftJoin(<span class="hljs-string">'a.features'</span>, <span class="hljs-string">'f2'</span>)->addSelect(<span class="hljs-string">'f2'</span>)
->leftJoin(<span class="hljs-string">'f2.property'</span>, <span class="hljs-string">'pr2'</span>)->addSelect(<span class="hljs-string">'pr2'</span>);
<span class="hljs-keyword">return</span> $qb;
}
}
</code></pre></div></div></div>