2012-09-22 5 views
1

J'ai une capacité de champ dans mytable.Tri du plus petit au plus grand

Je veux trier les extraire des données par la capacité du plus petit au plus grand

ces valeurs sont

6" x 12" 
6" x 12" 
6" x 18" 
6" x 12" 
10" x 20" 
12" x 24" 

Je veux que ce résultat

6" x 12" 
6" x 12" 
6" x 12" 
6" x 18" 
10" x 20" 
12" x 24" 

si j'utilisant cette requête

select * from mytable order by capacity ASC 

que le résultat est

10" x 20" 
12" x 24" 
6" x 12" 
6" x 12" 
6" x 12" 
6" x 18" 

si j'utilisant cette requête

select * from mytable order by capacity + 0 ASC 

que le résultat est

6" x 12" 
6" x 12" 
6" x 18" 
6" x 12" 
10" x 20" 
12" x 24" 
+0

Quels sont les noms des colonnes et des trucs pour que je puisse écrire un script pour vous si vous le souhaitez? –

+0

Est-il possible d'éditer la table? Si possible, vous trouverez probablement beaucoup plus agréable d'utiliser deux colonnes numériques pour stocker ces données, plutôt qu'une chaîne de caractères. – jmilloy

+0

champ de capacité comme varchar (255) –

Répondre

1

Une façon vous pouvez le faire est de boucle à travers les résultats et multiplier chaque valeur ensemble. En utilisant un tri personnalisé après, vous pourriez alors avoir le résultat que vous recherchez.

$sortedArray = array(); 
$array  = array(
    '6" x 12"', '6" x 18"', '6" x 12"', '6" x 12"', '10" x 12"' 
); 

// loop through rowset 
foreach ($array as $row) { 
    $parts = explode(' x ', str_replace('"', '', $row)); 
    $sortedArray[][($parts[0] * $parts[1])] = $row; 
} 

// custom sort - PHP 5.3 required for anonymous functions 
usort($sortedArray, function($a, $b) { 
    return (array_keys($a) > array_keys($b)); 
}); 

Sinon, si vous n'avez pas PHP 5.3, alors vous pouvez simplement changer le usort comme ceci:

function mySort($a, $b) 
{ 
    return (array_keys($a) > array_keys($b)); 
} 

usort($sortedArray, 'mySort'); 
1

changement cette requête

select * from mytable order by capacity ASC 

à

select * from mytable order by trim(capacity) ASC 

Il m'a aussi aidé il y a deux jours .. .

3

Vous devriez essayer ...

SELECT *, SUBSTRING_INDEX(capacity, 'x', 1) AS width, 
    SUBSTRING_INDEX(capacity, 'x', -1) AS height 
FROM mytable 
ORDER BY width+0 ASC, height+0 ASC 
1

Si vous ne pouvez pas factoriser la base de données pour stocker la taille en deux colonnes numériques, mais vous voulez atteindre le tri dans MySQL plutôt que php post-traitement, vous pouvez essayer d'extraire les dimensions et jeter les valeurs à des chiffres, quelque chose comme

SELECT dimensions 
FROM mytable 
ORDER BY 
    CAST(SUBSTRING_INDEX(dimensions, '"', 1) AS SIGNED) * 
    CAST(SUBSTRING_INDEX(LEFT(dimensions, LENGTH(dimensions)-1), ' ', -1) AS SIGNED) 
    ASC 

Ou, mieux, semblable à la réponse de Ashwini:

SELECT dimensions 
FROM mytable 
ORDER BY 
    (SUBSTRING_INDEX(dimensions, 'x', 1) + 0) * 
    (SUBSTRING_INDEX(dimensions, 'x', -1) + 0) 
    ASC 

Vous devrez probablement modifier les deux parties d'index de sous-chaîne.

Une autre façon d'extraire les valeurs dont vous avez besoin:

  • extrait la première dimension (la sous-chaîne du début à la première « : LEFT(dimensions, INSTR(dimensions, '"'))

  • extraire la deuxième dimension (la sous-chaîne à partir après le x de 1 à moins de la fin): droite (gauche (dimensions, longueur (dimensions-1)), (INSTR dimensions, 'x') + 1)

4

Ceci est un très mauvais schéma pour une table. La meilleure façon est de créer une table qui les sépare (les valeurs) en deux colonnes: largeur et hauteur. Exemple,

CREATE TABLE Dimension 
(
    ID INT AUTO_INCREMENT, 
    `Width` INT, 
    `Height` INT, 
    CONSTRAINT tb_pk PRIMARY KEY (ID) 
); 

alors vous pouvez maintenant insérer vos dossiers comme celui-ci,

INSERT INTO Dimension (`Width`, `Height`) VALUES (6, 12), (6,18), (10, 12); 

et il suffit d'utiliser cette requête pour commander le résultat

SELECT * 
FROM Dimension 
ORDER BY (`width` * `height`) DESC 

Mais pour répondre à votre question sans modifier le schéma, créez un USER DEFINE FUNCTION sur votre serveur,

CREATE FUNCTION SPLIT_STR 
(
    x VARCHAR(255), 
    delim VARCHAR(12), 
    pos INT 
) 
RETURNS VARCHAR(255) 
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos), 
     LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1), 
     delim, ''); 

puis utilisez cette requête,

SELECT CAST(SPLIT_STR(REPLACE(`capacity`, '"', '') ,'x', 1) as SIGNED) width, 
     CAST(SPLIT_STR(REPLACE(`capacity`, '"', '') ,'x', 2) as SIGNED) height 
FROM tableName 
ORDER BY (width * height) DESC 

SQLFiddle Demo

+2

C'est vraiment la meilleure réponse. Utilisez uniquement l'une des autres réponses s'il n'est absolument pas possible de modifier le schéma de la table. – jmilloy

+0

@jmilloy Je ne suis pas d'accord. C'est la meilleure solution, mais pas la meilleure réponse. C'est différent. Souvent, les OP n'ont pas accès, le temps, etc pour faire le genre de changements comme suggéré par John Woo. –

+0

@John Woo Pourquoi créez-vous une fonction SPLIT_STR au lieu d'utiliser SUBSTRING_INDEX? – jmilloy

1

-vous une faveur pour votre auto si vous le pouvez. Créer 2 colonnes separete pour ces données et, si vous ne voulez pas concaténer les valeurs en PHP, contactenate avec SQL:

select contact(width, '" x ', height, '"') as capacity from mytable order by width asc, height asc 

En outre, la commande par la largeur et la hauteur est separatelly beaucoup plus eficient et produit le résultat souhaité . Sont-ils stockés comme ça sous la forme d'une chaîne?

Questions connexes