MySQL - Seçili satır numarasını al


181

Öğeler sıralanırsa bir select deyimi çalıştırabilir ve satır numarasını alabilir miyim?

Ben böyle bir tablo var:

mysql> describe orders;
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| orderID     | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| itemID      | bigint(20) unsigned | NO   |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

Daha sonra kimliğe göre sipariş sayısını almak için bu sorguyu çalıştırabilirsiniz:

SELECT itemID, COUNT(*) as ordercount
FROM orders
GROUP BY itemID ORDER BY ordercount DESC;

Bu bana itemIDtablodaki her birinin bir sayısını verir :

+--------+------------+
| itemID | ordercount |
+--------+------------+
|    388 |          3 |
|    234 |          2 |
|   3432 |          1 |
|    693 |          1 |
|   3459 |          1 |
+--------+------------+

Ben de satır numarasını almak istiyorum, bu yüzden itemID=388ilk satır, 234ikinci, vb (aslında siparişlerin sıralaması, sadece ham bir sayı değil) söyleyebilirdim . Ben sonuç kümesi olsun Java bunu yapabilirim biliyorum, ama tamamen SQL işlemek için bir yol olup olmadığını merak ediyordum.

Güncelleme

Sıralamanın ayarlanması sonucu sonuç kümesine ekler, ancak düzgün sıralanmamıştır:

mysql> SET @rank=0;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @rank:=@rank+1 AS rank, itemID, COUNT(*) as ordercount
    -> FROM orders
    -> GROUP BY itemID ORDER BY rank DESC;
+------+--------+------------+
| rank | itemID | ordercount |
+------+--------+------------+
|    5 |   3459 |          1 |
|    4 |    234 |          2 |
|    3 |    693 |          1 |
|    2 |   3432 |          1 |
|    1 |    388 |          3 |
+------+--------+------------+
5 rows in set (0.00 sec)

1
İleride ORDER BY rank ASCbaşvurmak için: Kademe 1'den kademe 5'e sipariş vermek istiyorsanız (ASCending sırasına göre sıralama ile) kullanın. Ne demek istediğini ama düzgün sipariş değil
BlueCacti

Yanıtlar:


180

Bir göz atın bu .

Sorgunuzu şununla değiştirin:

SET @rank=0;
SELECT @rank:=@rank+1 AS rank, itemID, COUNT(*) as ordercount
  FROM orders
  GROUP BY itemID
  ORDER BY ordercount DESC;
SELECT @rank;

Son seçim sayınızdır.


1
Bu, sonuç kümesine rütbe ekler, ancak bunları doğru sıraya
George

1
Bunu tutmaya çalışın ORDER BY ordercount DESCve ardından tüm sorguyu SELECTilkinden her şeyi alan başka bir sektöre, ancak sıralama sütununa göre siparişleri sarın (bu durumda 0).
Mike Cialowicz

1
Bunun bir örneğini gösterebilir misiniz? Seçimleri nasıl sararım?
George

9
Swamibebop'un cevabına bir göz atın
thaddeusmt

1
@MikeCialowicz, Bu işe yaramıyor . Doğru cevap için çözümüme veya Swamibebop'un çözümüne bakın.
Pacerier

178
SELECT @rn:=@rn+1 AS rank, itemID, ordercount
FROM (
  SELECT itemID, COUNT(*) AS ordercount
  FROM orders
  GROUP BY itemID
  ORDER BY ordercount DESC
) t1, (SELECT @rn:=0) t2;

1
Açıkladığınız için teşekkürler, bu yaşadığım sıra dışı sorunu çözdü.
thaddeusmt

1
Teşekkürler, bu benim için gerçekten yararlı oldu :) Bir sonuç kümesinden satır 'dizinleri' almanın daha basit bir yolu olmadığına şaşırdım ... ama yine de teşekkürler bu kullanışlı oldu.
sıçan

Toplam sayı olarak SELECT \ @rn: = \ @ rn + 1 AS sıralamasında, itemID, ordercount, \ @tot: = \ @ tot + ordercount'ta ilk seçme deyimini değiştirerek artımlı bir toplam sayıyla dördüncü bir satır ekleyebilirsiniz. \ @Tot'un başlangıç ​​değerini tanımlamak için, t2'den sonra eklenmelidir: (SELECT \ @tot: = 0) t3. Mini-Markdown biçimlendirmesini atlatmak için kullanmam gereken \ @ herinden önce \ @ silin.
Jan Ehrhardt

2
Herkes alaka açıklayabilir t1ve t2?
Jared

2
@Jared, MySQL sözdiziminin orada olması gereken bir şey var. Her şey olabilir, hatta xve y.
Pacerier

31

Swamibebop'un çözümü işe yarıyor, ancak table.*sözdiziminden yararlanarak , iç kısımdaki sütun adlarını tekrarlamaktan kaçınabilirselect ve daha basit / daha kısa bir sonuç elde edebiliriz:

SELECT @r := @r+1 , 
       z.* 
FROM(/* your original select statement goes in here */)z, 
(SELECT @r:=0)y;

Böylece size:

SELECT @r := @r+1 , 
       z.* 
FROM(
     SELECT itemID, 
     count(*) AS ordercount
     FROM orders
     GROUP BY itemID
     ORDER BY ordercount DESC
    )z,
    (SELECT @r:=0)y;

Şans eseri @r := @r + 1bir select deyiminde kullanmanın neden işe yaradığını biliyor musunuz , ancak saklı bir yordamda ise declare r int; set r = 0;, şikayet ediyor (açık r := r +1)?
Dan M.

@Pacerier, aynı zamanda ikinci seçim bir yerde sıra garanti? Seçme tarafından cümle ile sipariş olmadan döndürülen satırların sırasının hiçbir yerde garanti edilmediğini ve en dıştaki seçimin, iç sipariş edilen seçimden seçilmesine rağmen, bunun bir istisna olabileceğini biliyorum. Bununla birlikte, Chibu'nun Mike'ıyla aynı kusura sahip olacağı için bunun nasıl doğru bir çözüm olduğunu göremiyorum - sipariş seçiminin kayıtlardan geçeceği ve numaralandırılacağı garantisi yok.
Dan M.

ORDER BY alan listesinde olmadığında neden çalışmadığı hakkında bir fikriniz var mı? Sonucuma
Kış

11

Bunu yapmak için MySQL değişkenlerini kullanabilirsiniz. Böyle bir şey işe yaramalıdır (yine de iki sorgudan oluşur).

SELECT 0 INTO @x;

SELECT itemID, 
       COUNT(*) AS ordercount, 
       (@x:=@x+1) AS rownumber 
FROM orders 
GROUP BY itemID 
ORDER BY ordercount DESC; 

2
Dikkatli olun, bu işe yaramaz çünkü değişken değerlendirildikten sonraorder by olur . Diğer sütunları kullanarak sipariş vererek denemeyi deneyin. Ayrıca hem deneme ve . Göreceksiniz ki, birçok kez başarısız olacaklar ve sadece çalıştıklarında , orijinal "seç" inizin sırası ile aynı sıraya göre saf şansla . Çözümümü ve / veya Swamibebop'un çözümünü görün. @xdescascorder by
Pacerier

@Pacerier bundan emin misin? Farklı bir örnekte benzer bir sorguda yoruldum (temel olarak sayıların sütunundan seçin ve sıralarına göre numaralandırın), var / row num tarafından sipariş edersem, ortaya çıkan satırların sırasını değiştirdiğinde, ancak her sayı aynı satır numarasına sahipti. Ama sayı sütununa göre sipariş edersem, ASC/ DESC, bu sayıların numaralandırılma sırasını değiştirir (en küçükten en büyüğe veya tam tersi). Yani bu durumda order byönce değerlendirilmiş gibi görünüyor .
Dan M.

1

Şimdi MySQL 8.0 ve MariaDB 10.2'de yerleşiktir:

SELECT
  itemID, COUNT(*) as ordercount,
  ROW_NUMBER OVER (PARTITION BY itemID ORDER BY rank DESC) as rank
FROM orders
GROUP BY itemID ORDER BY rank DESC
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.