<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Le blog de SQLpro &#187; intervale</title>
	<atom:link href="https://blog.developpez.com/sqlpro/ptag/intervale/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/sqlpro</link>
	<description>Le SQL pour SQL Server, PostGreSQL et tous les autres SGBDR</description>
	<lastBuildDate>Thu, 15 Oct 2020 12:59:17 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Tri combiné dans un arbre intervallaire</title>
		<link>https://blog.developpez.com/sqlpro/p11925/langage-sql-norme/tri-combine-dans-un-arbre-intervallaire</link>
		<comments>https://blog.developpez.com/sqlpro/p11925/langage-sql-norme/tri-combine-dans-un-arbre-intervallaire#comments</comments>
		<pubDate>Thu, 18 Apr 2013 07:42:23 +0000</pubDate>
		<dc:creator><![CDATA[SQLpro]]></dc:creator>
				<category><![CDATA[bases de données]]></category>
		<category><![CDATA[Langage SQL (norme)]]></category>
		<category><![CDATA[MS SQL Server]]></category>
		<category><![CDATA[PostGreSQL]]></category>
		<category><![CDATA[arborescence]]></category>
		<category><![CDATA[chemin]]></category>
		<category><![CDATA[fratrie]]></category>
		<category><![CDATA[intervale]]></category>
		<category><![CDATA[intervallaire]]></category>
		<category><![CDATA[path]]></category>
		<category><![CDATA[sibling]]></category>
		<category><![CDATA[tri]]></category>
		<category><![CDATA[tri mixte]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/sqlpro/?p=286</guid>
		<description><![CDATA[Trier des données dans le sens de l&#8217;arborescence et quand elle sont aux même niveau (frères) par ordre alphabétique (tri mixte arbre et alfa) est difficile à réaliser dans un arbre modélisé par intervalle. Mais le principe est assez simple. Il suffit de composer une nouvelle colonne constitué d&#8217;une alternance de nœud et d&#8217;ordre alphabétique [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Trier des données dans le sens de l&rsquo;arborescence et quand elle sont aux même niveau (frères) par ordre alphabétique (tri mixte arbre et alfa) est difficile à réaliser dans un arbre modélisé par intervalle. Mais le principe est assez simple. Il suffit de composer une nouvelle colonne constitué d&rsquo;une alternance de nœud et d&rsquo;ordre alphabétique relatif dans la fratrie, et de trier dessus. Voici comment faire. Cette technique s’appelle en anglais &laquo;&nbsp;sibling ordering&nbsp;&raquo;.<br />
<span id="more-286"></span> </p>
<p><strong>1 &#8211;  LE PROBLÈME</strong></p>
<p><strong>Voici notre jeu de test :</strong></p>
<p>Tout d&rsquo;abord la table</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE T_VEHICULE_VHC<br />
(VHC_ID &nbsp; &nbsp; &nbsp; &nbsp; INTEGER NOT NULL PRIMARY KEY,<br />
&nbsp;VHC_BG &nbsp; &nbsp; &nbsp; &nbsp; INTEGER,<br />
&nbsp;VHC_BD &nbsp; &nbsp; &nbsp; &nbsp; INTEGER,<br />
&nbsp;VHC_NIVEAU &nbsp; &nbsp; SMALLINT,<br />
&nbsp;VHC_NOM &nbsp; &nbsp; &nbsp; &nbsp;VARCHAR(16));</div></div>
<p>Et ses données :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">INSERT INTO T_VEHICULE_VHC VALUES ( 1, &nbsp;1, 26, 0, 'ALL');<br />
INSERT INTO T_VEHICULE_VHC VALUES ( 2, &nbsp;2, &nbsp;7, 1, 'SEA');<br />
INSERT INTO T_VEHICULE_VHC VALUES ( 3, &nbsp;8, 19, 1, 'EARTH');<br />
INSERT INTO T_VEHICULE_VHC VALUES ( 4, 20, 25, 1, 'AIR');<br />
INSERT INTO T_VEHICULE_VHC VALUES ( 5, &nbsp;3, &nbsp;4, 2, 'SUBMARINE');<br />
INSERT INTO T_VEHICULE_VHC VALUES ( 6, &nbsp;5, &nbsp;6, 2, 'BOAT');<br />
INSERT INTO T_VEHICULE_VHC VALUES ( 7, &nbsp;9, 10, 2, 'CAR');<br />
INSERT INTO T_VEHICULE_VHC VALUES ( 8, 11, 16, 2, 'TWO WHEELS');<br />
INSERT INTO T_VEHICULE_VHC VALUES ( 9, 17, 18, 2, 'TRUCK');<br />
INSERT INTO T_VEHICULE_VHC VALUES (10, 21, 22, 2, 'ROCKET');<br />
INSERT INTO T_VEHICULE_VHC VALUES (11, 23, 24, 2, 'PLANE');<br />
INSERT INTO T_VEHICULE_VHC VALUES (12, 12, 13, 3, 'MOTORCYCLE');<br />
INSERT INTO T_VEHICULE_VHC VALUES (13, 14, 15, 3, 'BICYCLE');</div></div>
<p><strong>Premier essai :</strong></p>
<p>Une simple requête telle que celle-ci :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SELECT CAST(SPACE(VHC_NIVEAU) + VHC_NOM AS VARCHAR(32)) AS NOM_IDENTE, <br />
&nbsp; &nbsp; &nbsp; &nbsp;VHC_ID, VHC_BG, VHC_BD, VHC_NIVEAU<br />
FROM &nbsp; T_VEHICULE_VHC &nbsp;<br />
ORDER &nbsp;BY VHC_BG;</div></div>
<p>Donne un résultat insatisfaisant :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">NOM_IDENTE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; VHC_ID &nbsp; &nbsp; &nbsp;VHC_BG &nbsp; &nbsp; &nbsp;VHC_BD &nbsp; &nbsp; &nbsp;VHC_NIVEAU<br />
-------------------------------- ----------- ----------- ----------- ----------<br />
ALL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 26 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0<br />
&nbsp;SEA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1<br />
&nbsp; SUBMARINE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2<br />
&nbsp; BOAT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2<br />
&nbsp;EARTH &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 19 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1<br />
&nbsp; CAR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2<br />
&nbsp; TWO WHEELS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;16 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2<br />
&nbsp; &nbsp;MOTORCYCLE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;13 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3<br />
&nbsp; &nbsp;BICYCLE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 13 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;14 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;15 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3<br />
&nbsp; TRUCK &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 17 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;18 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2<br />
&nbsp;AIR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 20 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;25 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1<br />
&nbsp; ROCKET &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;21 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;22 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2<br />
&nbsp; PLANE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;23 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;24 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2</div></div>
<p>Au niveau 1, &laquo;&nbsp;SEA&nbsp;&raquo; est avant &laquo;&nbsp;EARTH&nbsp;&raquo; qui lui même est avant &laquo;&nbsp;AIR&nbsp;&raquo;. Dans les deux roues (&laquo;&nbsp;TWO WHEELS&nbsp;&raquo;), &laquo;&nbsp;MOTORCYCLE&nbsp;&raquo; précède &laquo;&nbsp;BICYCLE&nbsp;&raquo;. Enfin, &laquo;&nbsp;CAR&nbsp;&raquo;, &laquo;&nbsp;TWO WHEELS&nbsp;&raquo; et &laquo;&nbsp;TRUCK&nbsp;&raquo; sont mélangés.<br />
Il n&rsquo;est pas possible d&rsquo;obtenir un meilleur ordonnancement directement basé sur les valeurs des colonnes actuelles de la table.</p>
<p>Mais la technique de l&rsquo;arbre intervallaire permet d&rsquo;ordonner les frères entre eux. Il suffit donc de bouger les bornes droites et gauches pour que cela corresponde à l&rsquo;ordre demandé. </p>
<p><strong>2 &#8211; PREMIÈRE SOLUTION</strong></p>
<p>Elle consiste donc à réordonner les bornes gauche et droite.</p>
<p>La nouvelle table pour ce faire :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">CREATE TABLE T_VEHICULE2_VHC<br />
(VHC_ID &nbsp; &nbsp; &nbsp; &nbsp; INTEGER NOT NULL PRIMARY KEY,<br />
&nbsp;VHC_BG &nbsp; &nbsp; &nbsp; &nbsp; INTEGER,<br />
&nbsp;VHC_BD &nbsp; &nbsp; &nbsp; &nbsp; INTEGER,<br />
&nbsp;VHC_NIVEAU &nbsp; &nbsp; SMALLINT,<br />
&nbsp;VHC_NOM &nbsp; &nbsp; &nbsp; &nbsp;VARCHAR(16));</div></div>
<p>Les données réarrangées :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">INSERT INTO T_VEHICULE2_VHC VALUES ( 1, &nbsp;1, 26, 0, 'ALL');<br />
INSERT INTO T_VEHICULE2_VHC VALUES ( 2, 20, 25, 1, 'SEA');<br />
INSERT INTO T_VEHICULE2_VHC VALUES ( 3, &nbsp;8, 19, 1, 'EARTH');<br />
INSERT INTO T_VEHICULE2_VHC VALUES ( 4, &nbsp;2, &nbsp;7, 1, 'AIR');<br />
INSERT INTO T_VEHICULE2_VHC VALUES ( 5, 23, 24, 2, 'SUBMARINE');<br />
INSERT INTO T_VEHICULE2_VHC VALUES ( 6, 21, 22, 2, 'BOAT');<br />
INSERT INTO T_VEHICULE2_VHC VALUES ( 7, &nbsp;9, 10, 2, 'CAR');<br />
INSERT INTO T_VEHICULE2_VHC VALUES ( 8, 13, 18, 2, 'TWO WHEELS');<br />
INSERT INTO T_VEHICULE2_VHC VALUES ( 9, 11, 12, 2, 'TRUCK');<br />
INSERT INTO T_VEHICULE2_VHC VALUES (10, &nbsp;5, &nbsp;6, 2, 'ROCKET');<br />
INSERT INTO T_VEHICULE2_VHC VALUES (11, &nbsp;3, &nbsp;4, 2, 'PLANE');<br />
INSERT INTO T_VEHICULE2_VHC VALUES (12, 16, 17, 3, 'MOTORCYCLE');<br />
INSERT INTO T_VEHICULE2_VHC VALUES (13, 14, 15, 3, 'BICYCLE');</div></div>
<p>La requête :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">SELECT CAST(SPACE(VHC_NIVEAU) + VHC_NOM AS VARCHAR(32)) AS NOM_IDENTE, <br />
&nbsp; &nbsp; &nbsp; &nbsp;VHC_ID, VHC_BG, VHC_BD, VHC_NIVEAU<br />
FROM &nbsp; T_VEHICULE2_VHC &nbsp;<br />
ORDER &nbsp;BY VHC_BG;</div></div>
<p>Le résultat :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">NOM_IDENTE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; VHC_ID &nbsp; &nbsp; &nbsp;VHC_BG &nbsp; &nbsp; &nbsp;VHC_BD &nbsp; &nbsp; &nbsp;VHC_NIVEAU<br />
-------------------------------- ----------- ----------- ----------- ----------<br />
ALL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 26 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0<br />
&nbsp;AIR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1<br />
&nbsp; PLANE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2<br />
&nbsp; ROCKET &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2<br />
&nbsp;EARTH &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 19 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1<br />
&nbsp; CAR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2<br />
&nbsp; TRUCK &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2<br />
&nbsp; TWO WHEELS &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 13 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;18 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2<br />
&nbsp; &nbsp;BICYCLE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 13 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;14 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;15 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3<br />
&nbsp; &nbsp;MOTORCYCLE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;16 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;17 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3<br />
&nbsp;SEA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 20 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;25 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1<br />
&nbsp; BOAT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 21 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;22 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2<br />
&nbsp; SUBMARINE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 23 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;24 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2</div></div>
<p><strong>Critique de la première solution</strong></p>
<p>La requête finale est simple. En revanche le coût est reporté lors des mises à jours (généralement peu nombreuses dans les arborescences) mais cela oblige souvent à réordonner tout l&rsquo;arbre (ce qui peut se minimiser en modélisant l&rsquo;arbre intervallaire à côté de la table contenant les données).<br />
De plus, elle n&rsquo;est pas satisfaisante si d&rsquo;autres colonnes complique la structure de la table et qu&rsquo;il faut en tenir compte dans la solution (par exemple de multiples arborescences).</p>
<p><strong>3 &#8211; UNE SOLUTION GÉNÉRIQUE</strong></p>
<p>Il existe une façon de faire globale, mais elle nécessite hélas une requête récursive en sus d&rsquo;être gourmande en données. Cette solution consiste à rajouter un &laquo;&nbsp;chemin&nbsp;&raquo; composé d&rsquo;une mixité de données comprenant les ancêtres alternés avec la position ordinale des frères entre eux. Pour la faire fonctionner correctement il est nécessaire d&rsquo;utiliser une fonction de remplissage que j&rsquo;ai intitulé PADMASK :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">--===========================================================================--<br />
-- Masque de caractères avec fusion alignée<br />
--===========================================================================--<br />
CREATE FUNCTION &nbsp;[F_PADMASK](@DATA NVARCHAR(1024), <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@MASK NVARCHAR(1024),<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;@ALIGN CHAR(6))<br />
RETURNS NVARCHAR(1024)<br />
AS<br />
/****************************************************************************** <br />
* Fonction de masque pour une donées polymorphe retournée en chaine de car. &nbsp; *<br />
******************************************************************************* <br />
* Fred. Brouard - http://sqlpro.developpez.com - www.sqlspot.com - 2012-07-12 * <br />
*******************************************************************************<br />
* Fusionne une donnée chaine avec un masque aligné à droite ou à gauche &nbsp; &nbsp; &nbsp; * <br />
* Exemples : &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*<br />
* SELECT dbo.F_PADMASK('ABC', '*****', 'LEFT' ) &nbsp; --&amp;gt; 'ABC**' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *<br />
* SELECT dbo.F_PADMASK(123, '00000', 'RIGHT') &nbsp; &nbsp; --&amp;gt; '00123' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *<br />
* SELECT dbo.F_PADMASK('ABCDEFG', '***', 'LEFT') &nbsp;--&amp;gt; 'EFG' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *<br />
* SELECT dbo.F_PADMASK('ABCDEFG', '***', 'RIGHT') --&amp;gt; 'ABC' &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *<br />
******************************************************************************/ <br />
BEGIN<br />
&nbsp; &nbsp;IF @MASK IS NULL RETURN '';<br />
&nbsp; &nbsp;IF @DATA IS NULL RETURN @MASK;<br />
&nbsp; &nbsp;IF UPPER(@ALIGN) IN ('RIGHT', 'DROIT', 'DROITE')<br />
&nbsp; &nbsp; &nbsp; SET @ALIGN = 'RIGHT'<br />
&nbsp; &nbsp;ELSE<br />
&nbsp; &nbsp; &nbsp; SET @ALIGN = 'LEFT'; &nbsp; &nbsp;<br />
-- masque avec alignement à gauche (alpha) &nbsp; <br />
&nbsp; &nbsp;IF @ALIGN = 'LEFT'<br />
&nbsp; &nbsp;BEGIN<br />
&nbsp; &nbsp; &nbsp; IF LEN(@MASK) &amp;gt; LEN(@DATA)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SET @DATA = @DATA + SUBSTRING(@MASK, LEN(@DATA) + 1, LEN(@MASK) - LEN(@DATA));<br />
&nbsp; &nbsp; &nbsp; IF LEN(@MASK) &nbsp;LEN(@DATA)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SET @DATA = SUBSTRING(@MASK, 1, LEN(@MASK) - LEN(@DATA)) + @DATA;<br />
&nbsp; &nbsp; &nbsp; IF LEN(@MASK) &amp;lt; LEN(@DATA)<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;SET @DATA = SUBSTRING(@DATA, LEN(@DATA) - LEN(@MASK) + 1, LEN(@MASK));<br />
&nbsp; &nbsp;END;<br />
&nbsp; &nbsp;RETURN @DATA; &nbsp; <br />
END<br />
GO</div></div>
<p><strong>NOTA</strong> : la fonction F_PADMASK a été écrite pour MS SQL Server, et peut aisément être traduite en PGPL/SQL pour PostGreSQL.</p>
<p>Voici maintenant la requête :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">WITH <br />
TA AS -- crée un indice numérique global d'ordonnancement alphabétique des libellés et le transforme en chaine complété avec des zéros<br />
(SELECT VHC_ID, VHC_BG, VHC_BD, VHC_NIVEAU, VHC_NOM, <br />
&nbsp; &nbsp; &nbsp; &nbsp; dbo.F_PADMASK(CAST(ROW_NUMBER() OVER(ORDER BY VHC_NOM) AS VARCHAR(10)), '00000000000', 'RIGHT') &nbsp;AS ORDRE<br />
&nbsp;FROM &nbsp; T_VEHICULE_VHC),<br />
T0 AS -- concatène un mixte de chemin et d'indice alphabétique dans une colonne intitulée PATH_MIXTE<br />
(SELECT VHC_ID, VHC_BG, VHC_BD, VHC_NIVEAU, VHC_NOM, ORDRE, <br />
&nbsp; &nbsp; &nbsp; &nbsp; CAST(dbo.F_PADMASK(VHC_NOM, '****************', 'LEFT') + ORDRE AS NVARCHAR(max)) AS PATH_MIXTE<br />
&nbsp;FROM &nbsp; TA<br />
&nbsp;WHERE &nbsp;VHC_NIVEAU = 0<br />
&nbsp;UNION ALL<br />
&nbsp;SELECT T1.VHC_ID, T1.VHC_BG, T1.VHC_BD, T1.VHC_NIVEAU, T1.VHC_NOM, T1.ORDRE, <br />
&nbsp; &nbsp; &nbsp; &nbsp; T0.PATH_MIXTE + dbo.F_PADMASK(T1.VHC_NOM, '****************', 'LEFT') + T1.ORDRE<br />
&nbsp;FROM &nbsp; TA AS T1<br />
&nbsp; &nbsp; &nbsp; &nbsp; INNER JOIN T0 <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ON T1.VHC_NIVEAU = T0.VHC_NIVEAU + 1<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;AND T1.VHC_BG &amp;gt; T0.VHC_BG<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;AND T1.VHC_BD &amp;lt; T0.VHC_BD)<br />
SELECT CAST(SPACE(VHC_NIVEAU) + VHC_NOM AS VARCHAR(32)) AS NOM_IDENTE, <br />
&nbsp; &nbsp; &nbsp; &nbsp;VHC_ID, VHC_BG, VHC_BD, VHC_NIVEAU, PATH_MIXTE<br />
FROM &nbsp; T0 &nbsp;<br />
ORDER &nbsp;BY PATH_MIXTE;</div></div>
<p>Comme indiqué, la colonne surnuméraire de tri, PATH_MIXTE, va contenir le chemin jusqu&rsquo;au nœud en cours avec entre chaque nom d&rsquo;élément sa position relative dans la fratrie. Le nécessité d&rsquo;utiliser la fonction de remplissage est lié au fait que notre colonne de tri contient une alternance de données numérique et alphabétique qu&rsquo;il faut ordonner ensemble. or les nombres sont alignés à droite et les mots à gauche. la fonction F_PADMASK permet de coordonner ces alignements. On comprend mieux la chose en voyant ce quelle contient :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">NOM_IDENTE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;VHC_ID &nbsp; &nbsp; &nbsp;VHC_BG &nbsp; &nbsp; &nbsp;VHC_BD &nbsp; &nbsp; &nbsp;VHC_NIVEAU PATH_MIXTE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
------------------- ----------- ----------- ----------- ---------- ------------------------------------------------------------------------------------------------------------<br />
ALL &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 26 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002<br />
&nbsp;AIR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 20 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;25 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002AIR*************00000000001<br />
&nbsp; PLANE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;23 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;24 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002AIR*************00000000001PLANE***********00000000008<br />
&nbsp; ROCKET &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;21 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;22 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002AIR*************00000000001ROCKET**********00000000009<br />
&nbsp;EARTH &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 19 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002EARTH***********00000000006<br />
&nbsp; CAR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 10 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002EARTH***********00000000006CAR*************00000000005<br />
&nbsp; TRUCK &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 17 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;18 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002EARTH***********00000000006TRUCK***********00000000012<br />
&nbsp; TWO WHEELS &nbsp; &nbsp; &nbsp; &nbsp;8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 11 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;16 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002EARTH***********00000000006TWO WHEELS******00000000013<br />
&nbsp; &nbsp;BICYCLE &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;13 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;14 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;15 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002EARTH***********00000000006TWO WHEELS******00000000013BICYCLE*********00000000003<br />
&nbsp; &nbsp;MOTORCYCLE &nbsp; &nbsp; &nbsp; 12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;12 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;13 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002EARTH***********00000000006TWO WHEELS******00000000013MOTORCYCLE******00000000007<br />
&nbsp;SEA &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002SEA*************00000000010<br />
&nbsp; BOAT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002SEA*************00000000010BOAT************00000000004<br />
&nbsp; SUBMARINE &nbsp; &nbsp; &nbsp; &nbsp; 5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ALL*************00000000002SEA*************00000000010SUBMARINE*******00000000011</div></div>
<p><strong>NOTA</strong> : le nombre de caractères de remplissage pour la partie alphabétique (ici colonne VHC_NOM) dépend de la longueur de la colonne (ici 16) définit à la construction de la table.</p>
<p><strong>ATTENTION</strong> : Certaines formulations, comme celle données ici sur Internet &laquo;&nbsp;<a href="http://stackoverflow.com/questions/2834156/ordering-recursive-result-set-in-sql-server" title="Ordering recursive result set in SQL Server">Ordering recursive result set in SQL Server</a>&nbsp;&raquo; sont fausses. Je vous laisse deviner pourquoi !</p>
<p><strong>Le site web sur le </strong><a href="http://sqlpro.developpez.com/">SQL et les SGBDR</a><br />
<img src="http://blog.developpez.com/media/Microsoft_MVP_logo_vertical Brouard 400.jpg" width="400" height="135" alt="MVP Microsoft SQL Server" /></p>
<pre>

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Frédéric Brouard, alias SQLpro, ARCHITECTE DE DONNÉES<br />
Expert &nbsp;S.G.B.D &nbsp;relationnelles &nbsp; et &nbsp; langage &nbsp;S.Q.L<br />
Moste &nbsp;Valuable &nbsp;Professionnal &nbsp;Microsoft &nbsp;SQL Server<br />
Société SQLspot &nbsp;: &nbsp;modélisation, conseil, formation,<br />
optimisation, &nbsp;audit, &nbsp;tuning, &nbsp;administration &nbsp;SGBDR<br />
Enseignant: CNAM PACA, ISEN Toulon, CESI Aix en Prov.</div></div>

</pre>
<p>L&rsquo;ntreprise <a href="http://www.sqlspot.com">SQL Spot</a></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
