Reputation: 103
I have a select statement :
$search = "SELECT Scene, Divinite, Attestation
FROM SceneDivList
WHERE BINARY Divinite = '$target'
ORDER BY FIELD( Scene);
$result = mysql_query($search, $con);
In this case the result will be alphabetically order based on the field 'scene'.
Is it possible to order the result not alphabetically but based on the following 'alphabet':
$alphabet = array( 1 => '-' , 2 => ',' , 3 => '.' , 4 => "A",
5 => "j", 6 => "a", 7 => "w", 8 => "b",
9 => "p", 10 => "f", 11 => "m", 12 => "n",
13 => "r", 14 => "h", 15 => "H", 16 => "x",
17 => "X", 18 => "s", 19 => "S", 20 => "q",
21 => "k", 22 => "g", 23 => "t", 24 => "T",
25 => "d", 26 => "D");
the result should then be:
SCENE ATTESTATION
jnD-Hr-m-nms,t DI.80,11
jrp DI.26,12
jrT,t DI.116,17
aAb,t DI.138,8
anx DI.12,5
antjw DI.148,10
wADw-msdm,t DI.144,11
bHsw DI.115,9
pr-n-nb=f DI.17,7
Upvotes: 2
Views: 113
Reputation: 3633
If you wanted to brute-string replace a field and sort by it, you need a recursive function in PHP to generate the string:
function replace( $fields ) {
if( empty( $fields ) ) return( "`Scene`" );
$t = each( $fields );
$pop = array_shift( $fields );
return( sprintf(
"replace(%s, '%s', '%s')",
replace($fields),
$t['key'],
str_pad($t['value'], 3, '0', STR_PAD_LEFT )
));
}
$alphabet = array( 1 => '-' , 2 => ',' , 3 => '.' , 4 => "A",
5 => "j", 6 => "a", 7 => "w", 8 => "b",
9 => "p", 10 => "f", 11 => "m", 12 => "n",
13 => "r", 14 => "h", 15 => "H", 16 => "x",
17 => "X", 18 => "s", 19 => "S", 20 => "q",
21 => "k", 22 => "g", 23 => "t", 24 => "T",
25 => "d", 26 => "D");
$sql = sprintf(
"SELECT Scene, Divinite, Attestation, %s as `neworder`
FROM SceneDivList
WHERE BINARY Divinite = '%s'
ORDER BY `neworder`",
replace(array_flip( $alphabet )),
"target <- whatever that is"
);
echo $sql;
At this point $sql will contain the following query:
SELECT Scene, Divinite, Attestation,
replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(
replace(replace(replace(replace(replace(replace(
`Scene`, 'D', '026'), 'd', '025'), 'T', '024'
), 't', '023'), 'g', '022'), 'k', '021'), 'q', '020'
), 'S', '019'), 's', '018'), 'X', '017'), 'x', '016'
), 'H', '015'), 'h', '014'), 'r', '013'), 'n', '012'
), 'm', '011'), 'f', '010'), 'p', '009'), 'b', '008'
), 'w', '007'), 'a', '006'), 'j', '005'), 'A', '004'
), '.', '003'), ',', '002'), '-', '001'
) as `neworder`
FROM SceneDivList
WHERE BINARY Divinite = 'target <- whatever that is'
ORDER BY `neworder`
Upvotes: 0
Reputation: 16468
Jon's answer is the best solution. But here there is a brutal php solution for you
$alphabet = array( 1 => '-' , 2 => ',' , 3 => '.' , 4 => "A",
5 => "j", 6 => "a", 7 => "w", 8 => "b",
9 => "p", 10 => "f", 11 => "m", 12 => "n",
13 => "r", 14 => "h", 15 => "H", 16 => "x",
17 => "X", 18 => "s", 19 => "S", 20 => "q",
21 => "k", 22 => "g", 23 => "t", 24 => "T",
25 => "d", 26 => "D");
$replace_engine = 'Scene';
foreach($alphabet as $k=>$char) {
$charint = sprintf("%03s", $k);
$replace_engine = "REPLACE(".$replace_engine.",'$char','$charint')";
}
$query = "SELECT $replace_engine as myalphabet, Scene FROM SceneDivList ORDER BY myalphabet";
Upvotes: 1
Reputation: 9012
While Jon's answer is the right approach, you might want to try the quick and dirty version by setting up a table (ID, C) where ID is (autoincrement) integer and C is a VARCHAR(1).
With joins the ordering could be achieved to whatever level is required.
$search = "SELECT s.Scene, s.Divinite, s.Attestation
FROM SceneDivList s
INNER JOIN CustomOrder o1 ON o1.C = SUBSTRING(s.Scene,0,1)
INNER JOIN CustomOrder o2 ON o2.C = SUBSTRING(s.Scene,1,1)
INNER JOIN CustomOrder o3 ON o3.C = SUBSTRING(s.Scene,2,1)
WHERE BINARY s.Divinite = '$target'
ORDER BY o1.ID, o2.ID, o3.ID, SUBSTRING(s.Scene,4);
$result = mysql_query($search, $con);
NOTE: While this can be done quick & dirty the query itself will be way slower than before.
Upvotes: 0
Reputation: 8202
There are two solutions: 1) order after query directly in code. the drawback is you always need to gather all the results so you could have performance problems. 2) add a column to the table with the ordering values based on the index of your array.
maybe you could create a mysql function to order on... but i don't know enough of custom mysql functions
... and the solution by Jon proposed 2 min before mine :D
Upvotes: 0
Reputation: 437494
The cleanest solution would be to define your own custom collation and specify that the Scene
column should use it. If you do that, the query will simply read ORDER BY Scene
and that's it (by the way, ORDER BY FIELD(Scene)
does not make sense -- did you check out what FIELD
does?).
Other than that, you could hack together a nightmare based on STR_REPLACE
to adapt the data to the collation instead of doing the opposite but I won't go there.
And of course you could sidestep all of this and do the sorting in PHP where it will be much more convenient, but this approach will not work for queries that join on subqueries that have to be sorted themselves.
Upvotes: 2