Czy istnieje dobry sposób na replikację funkcji SQL Server w MySQL ROW_NUMBER()
?
Na przykład:
SELECT
col1, col2,
ROW_NUMBER() OVER (PARTITION BY col1, col2 ORDER BY col3 DESC) AS intRow
FROM Table1
Następnie mógłbym na przykład dodać warunek ograniczenia intRow
do 1, aby uzyskać pojedynczy wiersz z najwyższym col3
dla każdej (col1, col2)
pary.
greatest-n-per-group
aby poprowadzić Cię do podobnych pytań.Sql-Server
znacznik, ponieważ był to najwyżej oceniany element w łączonym wyszukiwaniu znaczników, ale tak naprawdę nie dotyczy SQL Server.Odpowiedzi:
Jest to maksimum grupowe , jedno z najczęściej zadawanych pytań SQL (ponieważ wydaje się, że powinno to być łatwe, ale tak naprawdę nie jest).
Często staram się o samodzielne dołączenie:
„Pobierz wiersze w tabeli, dla których żaden inny wiersz z pasującym col1, col2 nie ma wyższego col3”. (Zauważysz to i większość innych grupowo maksymalnych rozwiązań zwróci wiele wierszy, jeśli więcej niż jeden wiersz ma ten sam col1, col2, col3. Jeśli to jest problem, możesz potrzebować dodatkowej obróbki).
źródło
SELECT t1.id FROM test t1 LEFT JOIN test t2 ON t1.id>t2.id WHERE t2.id IS NULL;
Czy nie wymagan*n/2 + n/2
porównania IS NULL, aby znaleźć pojedynczy wiersz? Czy zdarzają się jakieś optymalizacje, których nie widzę? Próbowałem zadać podobne pytanie do Billa w innym wątku, ale on chyba to zignorował.SELECT t0.col3 FROM table AS t0 WHERE NOT EXISTS (select 1 from table AS t1 ON t0.col1=t1.col1 AND t0.col2=t1.col2 AND t1.col3>t0.col3)
W MySQL nie ma funkcji rankingu. Najbliższe, jakie możesz uzyskać, to użyć zmiennej:
Tak. Gdyby to była Oracle, można użyć funkcji LEAD, aby osiągnąć szczyt przy następnej wartości. Na szczęście Quassnoi obejmuje logikę tego, co należy zaimplementować w MySQL .
źródło
SELECT @row_num:=@row_num+1 AS row_number, t.id FROM (SELECT * FROM table1 WHERE col = 264 ORDER BY id) t, (SELECT @row_num:=0) var;
Zawsze kończę według tego wzoru. Biorąc pod uwagę tę tabelę:
Możesz uzyskać ten wynik:
Uruchamiając to zapytanie, które nie wymaga żadnej zdefiniowanej zmiennej:
Mam nadzieję, że to pomaga!
źródło
<
,>
,<=
,>=
uchwyt CHAR i VARCHAR typy danych w kolejności alfabetycznej; Oczekuję, że jest dokładnie tym, czego szukasz.row_numbers <= 2
I wielkie dzięki za tę odpowiedź Mosty, jest idealny!źródło
Sprawdź ten artykuł, pokazuje on, jak naśladować SQL ROW_NUMBER () za pomocą partycji w MySQL. Natknąłem się na ten sam scenariusz w implementacji WordPress. Potrzebowałem ROW_NUMBER () i nie było go.
http://www.explodybits.com/2011/11/mysql-row-number/
Przykładem w tym artykule jest użycie pojedynczej partycji według pól. Aby podzielić na dodatkowe pola, możesz zrobić coś takiego:
Korzystanie z concat_ws obsługuje wartości null. Przetestowałem to na 3 polach, używając int, date i varchar. Mam nadzieję że to pomoże. Sprawdź artykuł, w którym łamie to zapytanie i wyjaśnia je.
źródło
limit 18446744073709551615
forceorder by
.concat_ws
z pusty ciąg''
jest niebezpiecznaconcat_ws('',12,3) = concat_ws('',1,23)
. Lepiej użyć separatora'_'
lub rozwiązania @Kenneth Xu.Od
MySQL 8.0.0
i powyżej można natywnie używać funkcji okienkowych.1.4 Co nowego w MySQL 8.0 :
ROW_NUMBER () over_clause :
Próbny:
DBFiddle Demo
źródło
Głosowałbym również za rozwiązaniem Mosty Mostacho z niewielkimi modyfikacjami jego kodu zapytania:
Co da ten sam wynik:
dla stołu:
Jedyną różnicą jest to, że zapytanie nie używa opcji ŁĄCZ i GRUPUJ WEDŁUG, zamiast tego korzysta z zagnieżdżonego wyboru.
źródło
Zdefiniowałbym funkcję:
wtedy mógłbym zrobić:
Teraz nie masz podzapytania, którego nie możesz mieć w widokach.
źródło
zapytanie o numer_wiersza w mysql
źródło
W MySQL nie ma takiej funkcji
rownum
,row_num()
ale sposób postępowania jest następujący:źródło
Rozwiązaniem, które okazało się najlepsze, było użycie takiego podzapytania:
Kolumny PARTITION BY po prostu porównuje się z „=” i oddziela je AND. Kolumny ORDER BY byłyby porównywane z „<” lub „>” i oddzielone OR.
Uważam, że jest to bardzo elastyczne, nawet jeśli jest trochę kosztowne.
źródło
Funkcji numeru początkowego nie można naśladować. Możesz uzyskać oczekiwane wyniki, ale na pewnym etapie najprawdopodobniej będziesz rozczarowany. Oto, co mówi dokumentacja mysql:
Pozdrawiam, Georgi.
źródło
MariaDB 10.2 implementuje „Funkcje okien”, w tym RANK (), ROW_NUMBER () i kilka innych rzeczy:
https://mariadb.com/kb/en/mariadb/window-functions/
Na podstawie przemówienia w Percona Live w tym miesiącu są dość dobrze zoptymalizowane.
Składnia jest identyczna z kodem w pytaniu.
źródło
Nie widzę żadnej prostej odpowiedzi dotyczącej części „PARTITION BY”, więc oto moja:
W tym prostym przykładzie podałem tylko jedną, ale możesz mieć kilka części „PARTITION BY”
źródło
Trochę późno, ale może też pomóc komuś, kto szuka odpowiedzi ...
Przykład wierszy / numer_wiersza - zapytanie rekurencyjne, które może być użyte w dowolnym SQL:
źródło
Pozwala to uzyskać taką samą funkcjonalność, jaką zapewnia ROW_NUMBER () AND PARTITION BY w MySQL
źródło
Trochę za późno, ale dzisiaj miałem tę samą potrzebę, więc przeszukałem Google i wreszcie znalazłem proste ogólne podejście tutaj w artykule Pinal Dave http://blog.sqlauthority.com/2014/03/09/mysql-reset-row -numer-for-each-group-partition-by-row-number /
Chciałem skoncentrować się na pierwotnym pytaniu Paula (to też był mój problem), dlatego podsumowałem moje rozwiązanie jako działający przykład.
Ponieważ chcemy podzielić na dwie kolumny, podczas iteracji utworzę zmienną SET, aby sprawdzić, czy nowa grupa została uruchomiona.
3 oznacza przy pierwszym parametrze MAKE_SET, że chcę obie wartości w SET (3 = 1 | 2). Oczywiście, jeśli nie mamy dwóch lub więcej kolumn konstruujących grupy, możemy wyeliminować operację MAKE_SET. Konstrukcja jest dokładnie taka sama. To działa dla mnie zgodnie z wymaganiami. Ogromne podziękowania dla Pinal Dave za jego wyraźną demonstrację.
źródło
ORDER BY
w podzapytaniu można zignorować (patrz mariadb.com/kb/en/mariadb/… ). Sugerowanym rozwiązaniem tego jest dodanieLIMIT 18446744073709551615
do podzapytania, które wymusza sortowanie. Może to jednak powodować problemy z wydajnością i nie dotyczy naprawdę cholernych wielkich tabel :)Może to być również rozwiązanie:
źródło
MySQL obsługuje ROW_NUMBER () od wersji 8.0+ .
Jeśli używasz MySQL w wersji 8.0 lub nowszej, sprawdź funkcję ROW_NUMBER (). W przeciwnym razie emulujesz funkcję ROW_NUMBER ().
Row_number () to funkcja rankingu, która zwraca kolejny numer wiersza, zaczynając od 1 dla pierwszego wiersza.
dla starszej wersji
źródło
Ważne: Zastanów się nad aktualizacją do MySQL 8+ i użyj zdefiniowanej i udokumentowanej funkcji ROW_NUMBER () oraz porzuć stare hacki powiązane z ograniczoną funkcjonalnością starą wersją MySQL
Oto jeden z tych hacków:
Odpowiedzi tutaj, które wykorzystują zmienne w zapytaniu głównie / wszystkie wydają się ignorować fakt, że dokumentacja mówi (parafraza):
Jako takie istnieje ryzyko, że wyrzucą złą odpowiedź, ponieważ zazwyczaj robią to
Jeśli zostaną one kiedykolwiek ocenione oddolnie, numer wiersza przestanie działać (brak partycji)
Musimy więc użyć czegoś z gwarantowaną kolejnością wykonania. Wpisz PRZYPADEK, GDY:
Jak zarys ld, kolejność przypisywania prevcol jest ważna - prevcol należy porównać z wartością bieżącego wiersza, zanim przypiszemy mu wartość z bieżącego wiersza (w przeciwnym razie byłaby to wartość aktualnego wiersza col, a nie wartość col poprzedniego wiersza) .
Oto jak to pasuje do siebie:
Pierwszy KIEDY jest oceniany. Jeśli kolumna tego wiersza jest taka sama jak kolumna poprzedniego wiersza, @r jest zwiększane i zwracane z CASE. Te zwracane wartości są przechowywane w @r. Cechą MySQL jest to, że przypisanie zwraca nową wartość tego, co jest przypisane do @r, w wierszach wyników.
Dla pierwszego wiersza w zestawie wyników @prevcol ma wartość null (jest inicjowane do null w podzapytaniu), więc ten predykat ma wartość false. Ten pierwszy predykat zwraca również wartość false przy każdej zmianie kolumny (bieżący wiersz różni się od poprzedniego). Powoduje to ocenę drugiego KIEDY.
Drugi predykat KIEDY jest zawsze fałszywy i istnieje wyłącznie w celu przypisania nowej wartości @prevcol. Ponieważ kolumna tego wiersza jest inna niż kolumna poprzedniego wiersza (wiemy o tym, ponieważ gdyby był taki sam, użyłby pierwszego KIEDY), musimy przypisać nową wartość, aby zachować ją do następnego testu. Ponieważ przypisanie jest wykonane, a następnie wynik przypisania jest porównywany z wartością NULL, a wszystko, co jest utożsamiane z wartością NULL, jest fałszywe, predykat ten jest zawsze fałszywy. Ale przynajmniej jego ocena polegała na zachowaniu wartości col z tego wiersza, dzięki czemu można ją oszacować na podstawie wartości col następnego rzędu
Ponieważ drugie KIEDY jest fałszem, oznacza to, że w sytuacjach, w których kolumna, którą dzielimy według (col) uległa zmianie, to ELSE daje nową wartość @r, restartując numerację od 1
Dochodzimy do sytuacji, w której:
Ma ogólną formę:
Przypisy:
P in pcol oznacza „partycja”, o in ocol oznacza „porządek” - w ogólnej formie usunąłem „poprzednią” z nazwy zmiennej, aby zmniejszyć bałagan wizualny
Nawiasy kwadratowe
(@pcolX := colX) = null
są ważne. Bez nich przypisz null do @pcolX i rzeczy przestaną działaćKompromisem jest to, że zestaw wyników musi być także uporządkowany według kolumn partycji, aby porównanie z poprzednią kolumną się sprawdziło. Nie można w ten sposób uporządkować numeru początkowego według jednej kolumny, ale zestaw wyników uporządkować w innej. Być może uda się to rozwiązać za pomocą podzapytań, ale uważam, że dokumenty stwierdzają również, że kolejność podzapytań może zostać zignorowana, chyba że zostanie użyte LIMIT i może to mieć wpływ występ
Nie zagłębiłem się w to poza testowaniem, czy metoda działa, ale jeśli istnieje ryzyko, że predykaty w drugim KIEDY zostaną zoptymalizowane (wszystko w porównaniu do wartości null jest zerowe / fałszywe, więc po co zawracać sobie głowy przypisaniem) i nie jest wykonywane , również się zatrzymuje. Wydaje mi się, że tak się nie dzieje, ale chętnie przyjmę komentarze i zaproponuję rozwiązanie, jeśli mogłoby się to zdarzyć
Rozsądne może być rzutowanie wartości null tworzących @pcolX na rzeczywiste typy kolumn w podzapytaniu, które tworzy zmienne @pcolX, a mianowicie:
select @pcol1 := CAST(null as INT), @pcol2 := CAST(null as DATE)
źródło
To nie jest najsolidniejsze rozwiązanie - ale jeśli chcesz po prostu utworzyć partycjonowany ranking na polu z kilkoma różnymi wartościami, może nie być nietypowo używać niektórych przypadków, gdy logika zawiera tyle zmiennych, ile potrzebujesz.
Coś takiego działało w przeszłości dla mnie:
Nadzieja, która ma sens / pomaga!
źródło
To działa idealnie dla mnie, aby utworzyć RowNumber, gdy mamy więcej niż jedną kolumnę. W tym przypadku dwie kolumny.
źródło
źródło
źródło