login  Naam:   Wachtwoord: 
Registreer je!
 Forum

Sorteren op string met getallen en punten (Opgelost)

Offline valles10 - 06/10/2015 17:00
Avatar van valles10HTML interesse Ik heb de volgende query:

  1. SELECT
  2. checklists.id,
  3. checklists.us AS us,
  4. customers.company AS company,
  5. CONCAT_WS(', ', built_by.name, (built_by2.name), (built_by3.name)) AS built_by, COALESCE(checked_by.name, '-') AS checked_by
  6. FROM `checklists`
  7. INNER JOIN customers ON customers.customer_id = checklists.customer
  8. LEFT OUTER JOIN users AS built_by ON checklists.built_by = built_by.id
  9. LEFT OUTER JOIN users AS built_by2 ON checklists.built_by2 = built_by2.id
  10. LEFT OUTER JOIN users AS built_by3 ON checklists.built_by3 = built_by3.id
  11. INNER JOIN users AS checked_by ON checklists.checked_by = checked_by.id


Nu wil ik enkel nog kunnen sorteren op 'checklists.us'. Het probleem echter is dat checklists.us een waarde bevat van bv. "US.2016.57" (x.y.z). Als ik gewoon het volgende toevoeg klopt de volgorde niet helemaal:
  1. ORDER BY checklists.us ASC

Nu is mijn vraag hoe ik ervoor kan zorgen dat ik eerst op y kan sorteren, vervolgens op z. Zodanig dat ik van:
US.2015.7
US.2016.45
USK.2016.789
US.2015.73
USK.2016.1

een lijst krijg die als volgt gesorteerd is:
USK.2016.789
US.2016.45
USK.2016.1
US.2015.73
US.2015.7

6 antwoorden

Gesponsorde links
Offline Thomas - 06/10/2015 23:41
Avatar van Thomas Moderator Dat lijkt eerder op y DESC, z DESC?

Het nadeel als je dat uitsplitst in je query op een of andere manier en het dan soorteert is waarschijnlijk dat je dit niet kunt indexeren (en het soorteren vervolgens nogal traag kan worden).

Beter om deze kolommen uit te splitsen in je/een tabel en eventueel te voorzien van een of meer indices?
Offline valles10 - 07/10/2015 09:29
Avatar van valles10 HTML interesse Heb ik ook zitten denken, maar had gehoopt dat ik het zou kunnen oplossen met de bestaande enkele kolom.

Ik ga toch nog even verder googelen en hopen dat hier iemand toch een antwoord weet 
Offline Thomas - 07/10/2015 11:54 (laatste wijziging 07/10/2015 11:56)
Avatar van Thomas Moderator Wat is "US.2015.73" uberhaupt? Is dit een serienummer of een soort van identificatie van iets?

Wat je ook zou kunnen doen is het in een zodanig formaat zetten dat het als string (dus alfabetisch, oftewel lexicografisch) gesorteerd kan worden. Hierbij zul je wel deze strings uit moeten vullen zodat ze elk dezelfde lengte hebben en de onderdelen van "meest relevant" naar "minst relevant" vermeld staan.

Als je dat doet heb je een vergelijkbare sortering als een numerieke. Denk bijvoorbeeld aan een DATE (yyyy-mm-dd) of DATETIME (yyyy-mm-dd hh:ii:ss). Dit zijn strings, maar volgen toch een logische/natuurlijke sortering door de volgorde van de onderdelen (van meest relevant (jaar) naar minst relevant (seconde)).

Vervolgens indexeer je deze ene kolom.

Dit hangt natuurlijk wel sterk af van de betekenis die deze data heeft, als je deze niet op bovenstaande manier kunt aanpassen zul je toch aan een andere oplossing moeten gaan denken, bijvoorbeeld de eerder voorgestelde opdeling in verschillende kolommen.

Wel moet je je bewust zijn van hoe string-sorteringen werken. Deze wijkt af van numerieke sorteringen, vergelijk (dit begint haast een klassiek voorbeeld te worden):

  1. mysql> SELECT 7 < 21;
  2. +--------+
  3. | 7 < 21 |
  4. +--------+
  5. | 1 |
  6. +--------+
  7. 1 row IN SET (0.00 sec)
  8.  
  9. mysql> SELECT '7' < '21';
  10. +------------+
  11. | '7' < '21' |
  12. +------------+
  13. | 0 |
  14. +------------+
  15. 1 row IN SET (0.00 sec)

En prent dit verschil goed in je geheugen.
Offline valles10 - 08/10/2015 11:34
Avatar van valles10 HTML interesse US is de nummer van de Assemblage bon.

Ik heb het anders aangepast, nl. als volgt:

  1. SELECT
  2. checklists.id,
  3. checklists.us AS us,
  4. customers.company AS company,
  5. CONCAT_WS(', ', built_by.name, (built_by2.name), (built_by3.name)) AS built_by,
  6. COALESCE(checked_by.name, '-') AS checked_by
  7. FROM `checklists`
  8. INNER JOIN customers ON customers.customer_id = checklists.customer
  9. LEFT OUTER JOIN users AS built_by ON checklists.built_by = built_by.id
  10. LEFT OUTER JOIN users AS built_by2 ON checklists.built_by2 = built_by2.id
  11. LEFT OUTER JOIN users AS built_by3 ON checklists.built_by3 = built_by3.id
  12. LEFT OUTER JOIN users AS checked_by ON checklists.checked_by = checked_by.id


vervolgens voor het sorteren voeg ik het volgende toe:

  1. ORDER BY SUBSTRING_INDEX(SUBSTRING_INDEX(checklists.us, '.', -2), '.', 1) $dir, SUBSTRING_INDEX(checklists.us, '.', -1) + 0 $dir


waar $dir ASC of DEC is natuurlijk. Works like a charm =)
Offline Thomas - 08/10/2015 13:21
Avatar van Thomas Moderator
Citaat:
Works like a charm =)

Om hoeveel records gaat dit op dit moment en hoe is de verwachte groei van je tabel(len)?

It might work like a charm now, but best be prepared for the future.

Als je tabelgrootte over een bepaalde punt heengaat dan draait het wellicht niet meer als een zonnetje.
Offline valles10 - 12/10/2015 14:44
Avatar van valles10 HTML interesse
FangorN schreef:
[..quote..]
Om hoeveel records gaat dit op dit moment en hoe is de verwachte groei van je tabel(len)?

It might work like a charm now, but best be prepared for the future.

Als je tabelgrootte over een bepaalde punt heengaat dan draait het wellicht niet meer als een zonnetje.


Het gaat telkens maar om 500 records die uit de database gehaald worden, dus in mijn geval doet het script wat het moet doen, ook performance-wise. Maar idd, met een aanzienlijk hoger aantal records is dit misschien niet de ideale oplossing.
Gesponsorde links
Je moet ingelogd zijn om een reactie te kunnen posten.
Actieve forumberichten
© 2002-2024 Sitemasters.be - Regels - Laadtijd: 0.182s