Sayı olarak SQL sipariş dizesi


137

VARCHARMySQL veritabanına kaydedilmiş numaralar var . INTBazı bağımlı durumlar nedeniyle onları yapamam .

Sıralama sırasında sayı olarak değil karakter olarak alıyor.

Veritabanında var

1 2 3 4 5 6 7 8 9 10...

Sayfamda şu şekilde sıralı liste gösteriliyor:

1 10 2 3 4 5 6 7 8 9

Artan sayılara göre nasıl görünmesini sağlayabilirim?


5
Şüphesiz, verileri dize yerine sayı olarak saklamış olmalısınız.
Oded

@Oded Yalnızca çok özel durumlarda sayısal değerine göre sipariş etmek istediğiniz bazı rastgele verileriniz (örneğin ayarlar) olabilir.
Glutexo

çok ilginç bir makale - MSSQL içindir, ancak MySQL için nispeten benzer olmalıdır: essentialsql.com/use-sql-server-to-sort-alphanumeric-values
AquaAlex

Yanıtlar:


256

Mümkünse, yalnızca sayıları depolarsanız sütunun veri türünü bir sayı olarak değiştirmeniz gerekir.

Bunu yapamıyorsanız o zaman bir şekilde sütun değer dağıtmak integer açıkça ile

select col from yourtable
order by cast(col as unsigned)

veya dolaylı olarak örneğin bir dönüşümü sayıya zorlayan bir matematiksel işlemle

select col from yourtable
order by col + 0

BTW MySQL, dizeleri soldan sağa dönüştürür. Örnekler:

string value  |  integer value after conversion
--------------+--------------------------------
'1'           |  1
'ABC'         |  0   /* the string does not contain a number, so the result is 0 */
'123miles'    |  123 
'$123'        |  0   /* the left side of the string does not start with a number */

3
col * 1 tarafından sipariş mükemmel çalışır. Bunun ardındaki sihir nedir? Üzgünüm ben profesyonel değilim bu yüzden bu aptalca bir soru olabilir ama nasıl * 1 numaraya değiştirmek yapar?
Jamol

12
MySQL ile dizeyi otomatik olarak bir sayıya dönüştürür1
juergen d

1
İlk seçenek en uygun olanıdır, ikincisi ekstra bir adımdır, ancak daha az işe yaramaz.
Manatax

5
ve karışık dize ve sayı varsa ve her ikisinin de sıralanmasını istiyorsanız, "col * 1, col göre sırala" kullanın
Hayden Thring

1
@superphonic: Sonuç olacak decimal.
juergen d

70

Başka bir yol, tek bir döküm kullanmadan.

(Dökümüne izin verilmeyen JPA 2.0 kullanan kişiler için)

select col from yourtable
order by length(col),col

EDIT: yalnızca pozitif tamsayılar için çalışır


9
Bu iyi bir, hem int hem de dize içeren sütun ile çalıştı
Sruit A.Suk

1
Bu her durumda çalışmaz. Başın üstünde, işe yaramayacak vakalar tam sayıların karışımlarıdır; negatif sayılar, baştaki sıfırlarla sayılar, kesir içeren sayılar ve sözcükler ve sayılar birleştirilir.
WonderWorker

3
herhangi bir döküm ve hokkabazlık türü olmadan harika bir çözüm, +1
Maksim Luzik 22:18

ilk görüşte işe yaramadı, ama işe yaradı! Teşekkür ederim!
try2fly.b4ucry


17

Sıraladığım sütunun alfa ve sayısal herhangi bir kombinasyonu var, bu yüzden bu yazıdaki önerileri başlangıç ​​noktası olarak kullandım ve bununla geldim.

DECLARE @tmp TABLE (ID VARCHAR(50));
INSERT INTO @tmp VALUES ('XYZ300');
INSERT INTO @tmp VALUES ('XYZ1002');
INSERT INTO @tmp VALUES ('106');
INSERT INTO @tmp VALUES ('206');
INSERT INTO @tmp VALUES ('1002');
INSERT INTO @tmp VALUES ('J206');
INSERT INTO @tmp VALUES ('J1002');

SELECT ID, (CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END) IsNum
FROM @tmp
ORDER BY IsNum, LEN(ID), ID;

Sonuçlar

ID
------------------------
106
206
1002
J206
J1002
XYZ300
XYZ1002

Bu yardımcı olur umarım


Sadece kullanabilir 1 - ISNUMERIC(ID)yerine (CASE WHEN ISNUMERIC(ID) = 1 THEN 0 ELSE 1 END)1 ve bunun tersi Değişikliğin 0.
S.Serpooshan

7

Bu benim için çalışıyor.

select * from tablename
order by cast(columnname as int) asc

nedenini açıklayabilir misin?
Slavik

en basit cevap, tam olarak gerekli olanı yapar, dizeyi bir int'e dönüştürür, daha sonra bu int tarafından artan düzende, korkak şeyler sipariş
etmeyin

4

Dönüştürmenin başka bir yolu.

Dize alanınız varsa, alanı veya sayısal kısmını şu şekilde dönüştürebilirsiniz: tüm tamsayı dizelerini eşit uzunlukta yapmak için baştaki sıfırlar ekleyin.

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( stringfield ) ) , stringfield ) 

veya 'tensymbols13', 'tensymbols1222' vb.

ORDER BY CONCAT( REPEAT(  "0", 18 - LENGTH( LEFT( stringfield , 10 ) ) ) , LEFT( stringfield , 10 ) ) 

2

Ayrıca harf öneki olan bir sıralama alanları arıyordum. İşte çözümü buldum. Bu, kimin aynı çözümü aradığına yardımcı olabilir.

Alan Değerleri:

FL01,FL02,FL03,FL04,FL05,...FL100,...FL123456789

select SUBSTRING(field,3,9) as field from table order by SUBSTRING(field,3,10)*1 desc

SUBSTRING(field,3,9) 9 koydum çünkü 9 maksimum 9 basamaklı tamsayı değerlerini tutmam için yeterli.

Sonuç 123456789 123456788 123456787 ... 100 99 ... 2 1 olacak


2

Bu, negatif sayılar, kesirler, dize, her şeyi işleyecektir:

ORDER BY ISNUMERIC(col) DESC, Try_Parse(col AS decimal(10,2)), col;

2

Kimin aynı çözümü aradığına yardımcı olabilir.

select * from tablename ORDER BY ABS(column_name)

0

AdonisJS kullanıyorsanız ve ABC-202, ABC-201 ... gibi karma kimlikleriniz varsa, ham sorguları Query Builder ile birleştirebilir ve yukarıdaki çözümü uygulayabilirsiniz ( https://stackoverflow.com/a/25061144/4040835 ) aşağıdaki gibi:

const sortField =
  'membership_id'
const sortDirection =
  'asc'
const subquery = UserProfile.query()
  .select(
    'user_profiles.id',
    'user_profiles.user_id',
    'user_profiles.membership_id',
    'user_profiles.first_name',
    'user_profiles.middle_name',
    'user_profiles.last_name',
    'user_profiles.mobile_number',
    'countries.citizenship',
    'states.name as state_of_origin',
    'user_profiles.gender',
    'user_profiles.created_at',
    'user_profiles.updated_at'
  )
  .leftJoin(
    'users',
    'user_profiles.user_id',
    'users.id'
  )
  .leftJoin(
    'countries',
    'user_profiles.nationality',
    'countries.id'
  )
  .leftJoin(
    'states',
    'user_profiles.state_of_origin',
    'states.id'
  )
  .orderByRaw(
    `SUBSTRING(:sortField:,3,15)*1 ${sortDirection}`,
    {
      sortField: sortField,
    }
  )
  .paginate(
    page,
    per_page
  )

NOTLAR: Bu satırda: SUBSTRING(:sortField:,3,15)*1 ${sortDirection},

  1. '3' , rakamlardan önceki son sayısal olmayan karakterin dizin numarasını ifade eder. Karışık kimliğiniz "ABC-123" ise, dizin numaranız 4 olacaktır.
  2. '15' , kısa çizgiden sonra olabildiğince çok rakam yakalamak için kullanılır.
  3. '1' , alt dize üzerinde alt diziyi etkili bir şekilde numaralandıran bir matematiksel işlem gerçekleştirir.

Ref 1: Ham sorgularda parametre bağlamaları hakkında daha fazla bilgiyi şu adreste bulabilirsiniz: https://knexjs.org/#Raw-Bindings Ref 2: Adonis Ham Sorguları: https://adonisjs.com/docs/4.1/query-builder# _raw_queries


-3

Alanınızı VARCHAR yerine INT olarak değiştirin.

Bazı bağımlı durumlar nedeniyle onları INT yapamam.

Ardından önce bağlı durumları düzeltin. Aksi takdirde, temel sorun üzerinde çalışıyorsunuz. MySQL CAST kullanmak bir seçenektir, ancak düzeltilmesi gereken kötü şemanızı maskelemektedir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.