Dane są przechwytywane i przechowywane z różnych powodów. Niezliczone godziny (a nawet większy budżet) zainwestowane w zbieranie, przetwarzanie, strukturyzację, walidację i ostatecznie przechowywanie danych; powiedzieć, że jest to cenny atut, to doprowadzić do sporu. W dzisiejszych czasach może być w rzeczywistości naszym najcenniejszym towarem.
Niektóre dane są wykorzystywane wyłącznie jako archiwum. Być może do nagrywania lub śledzenia wydarzeń, które miały miejsce w przeszłości. Ale drugą stroną medalu jest to, że dane historyczne mają wartość w podejmowaniu decyzji dotyczących przyszłych i przyszłych przedsięwzięć.
- W którym dniu odbędzie się nasza wyprzedaż? (Planowanie przyszłej sprzedaży na podstawie tego, jak radziliśmy sobie w przeszłości).
- Który sprzedawca osiągnął najlepsze wyniki w pierwszym kwartale? (Patrząc wstecz, kogo możemy nagrodzić za ich wysiłki.)
- Która restauracja jest najczęściej odwiedzana w połowie lipca? (Zbliża się sezon podróży... Komu możemy sprzedawać nasze artykuły spożywcze i towary?)
Dostajesz obraz. Korzystanie z dostępnych danych jest integralną częścią każdej organizacji.
Wiele firm buduje, bazuje i dostarcza usługi z danymi. Od tego zależą.
Kilka miesięcy temu, w zależności od tego, kiedy to czytasz, zacząłem chodzić na poważnie, aby ćwiczyć, aby schudnąć, zająć się zdrowiem i codziennie szukać odrobiny samotności w tym zabieganym świecie, w którym żyjemy.
Korzystałem z aplikacji mobilnej krokomierza, aby śledzić moje wędrówki, nawet biorąc pod uwagę, jakie buty nosiłem, ponieważ mam tendencję do wybrednego, jeśli chodzi o obuwie.
Chociaż te dane nie są tak ważne, jak te wymienione w powyższych scenariuszach, dla mnie kluczowym elementem w nauce czegokolwiek jest użycie czegoś, co mnie interesuje, do czego mogę się odnieść i co rozumiem.
Funkcje okien były na moim radarze od dłuższego czasu. Pomyślałem więc, że spróbuję swoich sił w kilku z nich w tym poście. Ponieważ ostatnio był wspierany w MySQL 8 (odwiedź ten blog Manynines, w którym pisałem o aktualizacjach MySQL 8 i nowych dodatkach, gdzie pokrótce o nich wspominam), ten ekosystem jest tym, którego będę tutaj używał. Ostrzegam, nie jestem guru funkcji analizy okien.
Co to jest funkcja okna MySQL?
Dokumentacja MySQL definiuje je w następujący sposób: „Funkcja okna wykonuje operację podobną do agregacji na zestawie wierszy zapytań. Jednak podczas gdy operacja agregująca grupuje wiersze zapytań w pojedynczy wiersz wyników, funkcja okna generuje wynik dla każdy wiersz zapytania:"
Zbiór danych i konfiguracja tego posta
Przechwycone dane z moich spacerów przechowuję w tej tabeli:
mysql> DESC hiking_stats;
+-----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+-------+
| day_walked | date | YES | | NULL | |
| burned_calories | decimal(4,1) | YES | | NULL | |
| distance_walked | decimal(4,2) | YES | | NULL | |
| time_walking | time | YES | | NULL | |
| pace | decimal(2,1) | YES | | NULL | |
| shoes_worn | text | YES | | NULL | |
| trail_hiked | text | YES | | NULL | |
+-----------------+--------------+------+-----+---------+-------+
7 rows in set (0.01 sec)
W tym miejscu znajdują się dane z blisko 90 dni:
mysql> SELECT COUNT(*) FROM hiking_stats;
+----------+
| COUNT(*) |
+----------+
| 84 |
+----------+
1 row in set (0.00 sec)
Przyznam się, że jestem wybredna jeśli chodzi o moje obuwie, więc ustalmy, która para butów najbardziej mi się podobała:
mysql> SELECT DISTINCT shoes_worn, COUNT(*)
-> FROM hiking_stats
-> GROUP BY shoes_worn;
+---------------------------------------+----------+
| shoes_worn | COUNT(*) |
+---------------------------------------+----------+
| New Balance Trail Runners-All Terrain | 30 |
| Oboz Sawtooth Low | 47 |
| Keen Koven WP(keen-dry) | 6 |
| New Balance 510v2 | 1 |
+---------------------------------------+----------+
4 rows in set (0.00 sec)
Aby zapewnić lepszą, wykonalną demonstrację na ekranie, ograniczę pozostałą część wyników zapytań tylko do tych, które dotyczą ulubionych butów, które nosiłem 47 razy.
Mam też kolumnę trail_hiked, a ponieważ byłem w „trybie ćwiczeń ultra „w ciągu tego prawie 3 miesięcznego okresu liczyłem nawet kalorie podczas wypychania podwórka:
mysql> SELECT DISTINCT trail_hiked, COUNT(*)
-> FROM hiking_stats
-> GROUP BY trail_hiked;
+------------------------+----------+
| trail_hiked | COUNT(*) |
+------------------------+----------+
| Yard Mowing | 14 |
| Sandy Trail-Drive | 20 |
| West Boundary | 29 |
| House-Power Line Route | 10 |
| Tree Trail-extended | 11 |
+------------------------+----------+
5 rows in set (0.01 sec)
Jednak, aby jeszcze bardziej ograniczyć zestaw danych, odfiltruję również te wiersze:
mysql> SELECT COUNT(*)
-> FROM hiking_stats
-> WHERE shoes_worn = 'Oboz Sawtooth Low'
-> AND
-> trail_hiked <> 'Yard Mowing';
+----------+
| COUNT(*) |
+----------+
| 40 |
+----------+
1 row in set (0.01 sec)
Ze względu na prostotę i łatwość użytkowania stworzę WIDOK kolumn do pracy:
mysql> CREATE VIEW vw_fav_shoe_stats AS
-> (SELECT day_walked, burned_calories, distance_walked, time_walking, pace, trail_hiked
-> FROM hiking_stats
-> WHERE shoes_worn = 'Oboz Sawtooth Low'
-> AND trail_hiked <> 'Yard Mowing');
Query OK, 0 rows affected (0.19 sec)
Pozostawiając mi ten zestaw danych:
mysql> SELECT * FROM vw_fav_shoe_stats;
+------------+-----------------+-----------------+--------------+------+------------------------+
| day_walked | burned_calories | distance_walked | time_walking | pace | trail_hiked |
+------------+-----------------+-----------------+--------------+------+------------------------+
| 2018-06-03 | 389.6 | 4.11 | 01:13:19 | 3.4 | Sandy Trail-Drive |
| 2018-06-04 | 394.6 | 4.26 | 01:14:15 | 3.4 | Sandy Trail-Drive |
| 2018-06-06 | 384.6 | 4.10 | 01:13:14 | 3.4 | Sandy Trail-Drive |
| 2018-06-07 | 382.7 | 4.12 | 01:12:52 | 3.4 | Sandy Trail-Drive |
| 2018-06-17 | 296.3 | 2.82 | 00:55:45 | 3.0 | West Boundary |
| 2018-06-18 | 314.7 | 3.08 | 00:59:13 | 3.1 | West Boundary |
| 2018-06-20 | 338.5 | 3.27 | 01:03:42 | 3.1 | West Boundary |
| 2018-06-21 | 339.5 | 3.40 | 01:03:54 | 3.2 | West Boundary |
| 2018-06-24 | 392.4 | 3.76 | 01:13:51 | 3.1 | House-Power Line Route |
| 2018-06-25 | 362.1 | 3.72 | 01:08:09 | 3.3 | West Boundary |
| 2018-06-26 | 380.5 | 3.94 | 01:11:36 | 3.3 | West Boundary |
| 2018-07-03 | 323.7 | 3.29 | 01:00:55 | 3.2 | West Boundary |
| 2018-07-04 | 342.8 | 3.47 | 01:04:31 | 3.2 | West Boundary |
| 2018-07-06 | 375.7 | 3.80 | 01:10:42 | 3.2 | West Boundary |
| 2018-07-07 | 347.6 | 3.40 | 01:05:25 | 3.1 | Sandy Trail-Drive |
| 2018-07-08 | 351.6 | 3.58 | 01:06:09 | 3.2 | West Boundary |
| 2018-07-09 | 336.0 | 3.28 | 01:03:13 | 3.1 | West Boundary |
| 2018-07-11 | 375.2 | 3.81 | 01:10:37 | 3.2 | West Boundary |
| 2018-07-12 | 325.9 | 3.28 | 01:01:20 | 3.2 | West Boundary |
| 2018-07-15 | 382.9 | 3.91 | 01:12:03 | 3.3 | House-Power Line Route |
| 2018-07-16 | 368.6 | 3.72 | 01:09:22 | 3.2 | West Boundary |
| 2018-07-17 | 339.4 | 3.46 | 01:03:52 | 3.3 | West Boundary |
| 2018-07-18 | 368.1 | 3.72 | 01:08:28 | 3.3 | West Boundary |
| 2018-07-19 | 339.2 | 3.44 | 01:03:06 | 3.3 | West Boundary |
| 2018-07-22 | 378.3 | 3.76 | 01:10:22 | 3.2 | West Boundary |
| 2018-07-23 | 322.9 | 3.28 | 01:00:03 | 3.3 | West Boundary |
| 2018-07-24 | 386.4 | 3.81 | 01:11:53 | 3.2 | West Boundary |
| 2018-07-25 | 379.9 | 3.83 | 01:10:39 | 3.3 | West Boundary |
| 2018-07-27 | 378.3 | 3.73 | 01:10:21 | 3.2 | West Boundary |
| 2018-07-28 | 337.4 | 3.39 | 01:02:45 | 3.2 | Sandy Trail-Drive |
| 2018-07-29 | 348.7 | 3.50 | 01:04:52 | 3.2 | West Boundary |
| 2018-07-30 | 361.6 | 3.69 | 01:07:15 | 3.3 | West Boundary |
| 2018-07-31 | 359.9 | 3.66 | 01:06:57 | 3.3 | West Boundary |
| 2018-08-01 | 336.1 | 3.37 | 01:01:48 | 3.3 | West Boundary |
| 2018-08-03 | 259.9 | 2.57 | 00:47:47 | 3.2 | West Boundary |
| 2018-08-05 | 341.2 | 3.37 | 01:02:44 | 3.2 | West Boundary |
| 2018-08-06 | 357.7 | 3.64 | 01:05:46 | 3.3 | West Boundary |
| 2018-08-17 | 184.2 | 1.89 | 00:39:00 | 2.9 | Tree Trail-extended |
| 2018-08-18 | 242.9 | 2.53 | 00:51:25 | 3.0 | Tree Trail-extended |
| 2018-08-30 | 204.4 | 1.95 | 00:37:35 | 3.1 | House-Power Line Route |
+------------+-----------------+-----------------+--------------+------+------------------------+
40 rows in set (0.00 sec)
Pierwszą funkcją okna, której się przyjrzę, jest ROW_NUMBER().
Załóżmy, że chcę uzyskać zestaw wyników uporządkowany według kolumny burned_calories dla miesiąca „lipiec”.
Oczywiście mogę pobrać te dane za pomocą tego zapytania:
mysql> SELECT day_walked, burned_calories, trail_hiked
-> FROM vw_fav_shoe_stats
-> WHERE MONTHNAME(day_walked) = 'July'
-> ORDER BY burned_calories DESC;
+------------+-----------------+------------------------+
| day_walked | burned_calories | trail_hiked |
+------------+-----------------+------------------------+
| 2018-07-24 | 386.4 | West Boundary |
| 2018-07-15 | 382.9 | House-Power Line Route |
| 2018-07-25 | 379.9 | West Boundary |
| 2018-07-22 | 378.3 | West Boundary |
| 2018-07-27 | 378.3 | West Boundary |
| 2018-07-06 | 375.7 | West Boundary |
| 2018-07-11 | 375.2 | West Boundary |
| 2018-07-16 | 368.6 | West Boundary |
| 2018-07-18 | 368.1 | West Boundary |
| 2018-07-30 | 361.6 | West Boundary |
| 2018-07-31 | 359.9 | West Boundary |
| 2018-07-08 | 351.6 | West Boundary |
| 2018-07-29 | 348.7 | West Boundary |
| 2018-07-07 | 347.6 | Sandy Trail-Drive |
| 2018-07-04 | 342.8 | West Boundary |
| 2018-07-17 | 339.4 | West Boundary |
| 2018-07-19 | 339.2 | West Boundary |
| 2018-07-28 | 337.4 | Sandy Trail-Drive |
| 2018-07-09 | 336.0 | West Boundary |
| 2018-07-12 | 325.9 | West Boundary |
| 2018-07-03 | 323.7 | West Boundary |
| 2018-07-23 | 322.9 | West Boundary |
+------------+-----------------+------------------------+
22 rows in set (0.01 sec)
Jednak z dowolnego powodu (może z osobistej satysfakcji) chcę nagrodzić ranking wśród zwróconych wierszy zaczynających się od 1 wskazującego na najwyższą liczbę spalonych_kalorii, aż do (n) wierszy w zestawie wyników.
ROW_NUMBER(), poradzi sobie z tym bez problemu:
mysql> SELECT day_walked, burned_calories,
-> ROW_NUMBER() OVER(ORDER BY burned_calories DESC)
-> AS position, trail_hiked
-> FROM vw_fav_shoe_stats
-> WHERE MONTHNAME(day_walked) = 'July';
+------------+-----------------+----------+------------------------+
| day_walked | burned_calories | position | trail_hiked |
+------------+-----------------+----------+------------------------+
| 2018-07-24 | 386.4 | 1 | West Boundary |
| 2018-07-15 | 382.9 | 2 | House-Power Line Route |
| 2018-07-25 | 379.9 | 3 | West Boundary |
| 2018-07-22 | 378.3 | 4 | West Boundary |
| 2018-07-27 | 378.3 | 5 | West Boundary |
| 2018-07-06 | 375.7 | 6 | West Boundary |
| 2018-07-11 | 375.2 | 7 | West Boundary |
| 2018-07-16 | 368.6 | 8 | West Boundary |
| 2018-07-18 | 368.1 | 9 | West Boundary |
| 2018-07-30 | 361.6 | 10 | West Boundary |
| 2018-07-31 | 359.9 | 11 | West Boundary |
| 2018-07-08 | 351.6 | 12 | West Boundary |
| 2018-07-29 | 348.7 | 13 | West Boundary |
| 2018-07-07 | 347.6 | 14 | Sandy Trail-Drive |
| 2018-07-04 | 342.8 | 15 | West Boundary |
| 2018-07-17 | 339.4 | 16 | West Boundary |
| 2018-07-19 | 339.2 | 17 | West Boundary |
| 2018-07-28 | 337.4 | 18 | Sandy Trail-Drive |
| 2018-07-09 | 336.0 | 19 | West Boundary |
| 2018-07-12 | 325.9 | 20 | West Boundary |
| 2018-07-03 | 323.7 | 21 | West Boundary |
| 2018-07-23 | 322.9 | 22 | West Boundary |
+------------+-----------------+----------+------------------------+
22 rows in set (0.00 sec)
Możesz zobaczyć wiersz z ilością spalonych_kalorii 386,4 ma pozycję 1, podczas gdy wiersz o wartości 322,9 ma 22, co jest najmniejszą (lub najniższą) kwotą wśród zwróconych wierszy.
W miarę postępów użyję ROW_NUMBER() do czegoś bardziej interesującego. Dopiero gdy dowiedziałem się, że jest używany w tym kontekście, naprawdę zdałem sobie sprawę z jego prawdziwej mocy.
Następnie przejdźmy do funkcji okna RANK(), aby zapewnić inny rodzaj „rankingu ' wśród rzędów. Nadal będziemy kierować się wartością kolumny burned_calories. I chociaż RANK() jest podobna do ROW_NUMBER(), ponieważ nieco porządkuje wiersze, w pewnych okolicznościach wprowadza subtelną różnicę.
Jeszcze bardziej ograniczę liczbę wierszy jako całości, filtrując wszelkie rekordy nie w miesiącu „lipiec”, ale kierując się na określony szlak:
mysql> SELECT day_walked, burned_calories,
-> RANK() OVER(ORDER BY burned_calories DESC) AS position,
-> trail_hiked
-> FROM vw_fav_shoe_stats
-> WHERE MONTHNAME(day_walked) = 'July'
-> AND trail_hiked = 'West Boundary';
+------------+-----------------+----------+---------------+
| day_walked | burned_calories | position | trail_hiked |
+------------+-----------------+----------+---------------+
| 2018-07-24 | 386.4 | 1 | West Boundary |
| 2018-07-25 | 379.9 | 2 | West Boundary |
| 2018-07-22 | 378.3 | 3 | West Boundary |
| 2018-07-27 | 378.3 | 3 | West Boundary |
| 2018-07-06 | 375.7 | 5 | West Boundary |
| 2018-07-11 | 375.2 | 6 | West Boundary |
| 2018-07-16 | 368.6 | 7 | West Boundary |
| 2018-07-18 | 368.1 | 8 | West Boundary |
| 2018-07-30 | 361.6 | 9 | West Boundary |
| 2018-07-31 | 359.9 | 10 | West Boundary |
| 2018-07-08 | 351.6 | 11 | West Boundary |
| 2018-07-29 | 348.7 | 12 | West Boundary |
| 2018-07-04 | 342.8 | 13 | West Boundary |
| 2018-07-17 | 339.4 | 14 | West Boundary |
| 2018-07-19 | 339.2 | 15 | West Boundary |
| 2018-07-09 | 336.0 | 16 | West Boundary |
| 2018-07-12 | 325.9 | 17 | West Boundary |
| 2018-07-03 | 323.7 | 18 | West Boundary |
| 2018-07-23 | 322.9 | 19 | West Boundary |
+------------+-----------------+----------+---------------+
19 rows in set (0.01 sec)
Zauważyłeś tu coś dziwnego? Różni się od ROW_NUMBER()?
Sprawdź wartość pozycji dla tych wierszy „2018-07-22” i „2018-07-27”. Remisują na trzecim miejscu.
Nie bez powodu, ponieważ wartość burned_calorie wynosząca 378,3 jest obecna w obu wierszach.
Jak uszeregowałaby je ROW_NUMBER()?
Dowiedzmy się:
mysql> SELECT day_walked, burned_calories,
-> ROW_NUMBER() OVER(ORDER BY burned_calories DESC) AS position,
-> trail_hiked
-> FROM vw_fav_shoe_stats
-> WHERE MONTHNAME(day_walked) = 'July'
-> AND trail_hiked = 'West Boundary';
+------------+-----------------+----------+---------------+
| day_walked | burned_calories | position | trail_hiked |
+------------+-----------------+----------+---------------+
| 2018-07-24 | 386.4 | 1 | West Boundary |
| 2018-07-25 | 379.9 | 2 | West Boundary |
| 2018-07-22 | 378.3 | 3 | West Boundary |
| 2018-07-27 | 378.3 | 4 | West Boundary |
| 2018-07-06 | 375.7 | 5 | West Boundary |
| 2018-07-11 | 375.2 | 6 | West Boundary |
| 2018-07-16 | 368.6 | 7 | West Boundary |
| 2018-07-18 | 368.1 | 8 | West Boundary |
| 2018-07-30 | 361.6 | 9 | West Boundary |
| 2018-07-31 | 359.9 | 10 | West Boundary |
| 2018-07-08 | 351.6 | 11 | West Boundary |
| 2018-07-29 | 348.7 | 12 | West Boundary |
| 2018-07-04 | 342.8 | 13 | West Boundary |
| 2018-07-17 | 339.4 | 14 | West Boundary |
| 2018-07-19 | 339.2 | 15 | West Boundary |
| 2018-07-09 | 336.0 | 16 | West Boundary |
| 2018-07-12 | 325.9 | 17 | West Boundary |
| 2018-07-03 | 323.7 | 18 | West Boundary |
| 2018-07-23 | 322.9 | 19 | West Boundary |
+------------+-----------------+----------+---------------+
19 rows in set (0.06 sec)
Hmmm...
Tym razem nie ma żadnych powiązań w numeracji kolumny pozycji.
Ale kto ma pierwszeństwo?
O ile mi wiadomo, w celu przewidywalnej kolejności prawdopodobnie będziesz musiał określić ją za pomocą innych dodatkowych środków w zapytaniu (np. w tym przypadku kolumny time_walking?).
Ale nie skończyliśmy jeszcze z opcjami rankingu. Oto DENSE_RANK():
mysql> SELECT day_walked, burned_calories,
-> DENSE_RANK() OVER(ORDER BY burned_calories DESC) AS position,
-> trail_hiked
-> FROM vw_fav_shoe_stats
-> WHERE MONTHNAME(day_walked) = 'July'
-> AND trail_hiked = 'West Boundary';
+------------+-----------------+----------+---------------+
| day_walked | burned_calories | position | trail_hiked |
+------------+-----------------+----------+---------------+
| 2018-07-24 | 386.4 | 1 | West Boundary |
| 2018-07-25 | 379.9 | 2 | West Boundary |
| 2018-07-22 | 378.3 | 3 | West Boundary |
| 2018-07-27 | 378.3 | 3 | West Boundary |
| 2018-07-06 | 375.7 | 4 | West Boundary |
| 2018-07-11 | 375.2 | 5 | West Boundary |
| 2018-07-16 | 368.6 | 6 | West Boundary |
| 2018-07-18 | 368.1 | 7 | West Boundary |
| 2018-07-30 | 361.6 | 8 | West Boundary |
| 2018-07-31 | 359.9 | 9 | West Boundary |
| 2018-07-08 | 351.6 | 10 | West Boundary |
| 2018-07-29 | 348.7 | 11 | West Boundary |
| 2018-07-04 | 342.8 | 12 | West Boundary |
| 2018-07-17 | 339.4 | 13 | West Boundary |
| 2018-07-19 | 339.2 | 14 | West Boundary |
| 2018-07-09 | 336.0 | 15 | West Boundary |
| 2018-07-12 | 325.9 | 16 | West Boundary |
| 2018-07-03 | 323.7 | 17 | West Boundary |
| 2018-07-23 | 322.9 | 18 | West Boundary |
+------------+-----------------+----------+---------------+
19 rows in set (0.00 sec)
Remis pozostaje, jednak numeracja jest inna w przypadku liczenia rzędów , kontynuując pozostałe wyniki.
Tam, gdzie RANK() rozpoczyna liczenie od 5 po remisach, DENSE_RANK() wybiera następną liczbę, która w tym przypadku wynosi 4, ponieważ remis miał miejsce w rzędzie 3.
Będę pierwszym, który przyzna, że te różne wzorce rankingu wierszy są dość interesujące, ale jak można ich użyć do uzyskania sensownego zestawu wyników?
ClusterControlSingle Console dla całej infrastruktury bazy danychDowiedz się, co jeszcze nowego w ClusterControlZainstaluj ClusterControl ZA DARMODodatkowa myśl
Muszę udzielić kredytu tam, gdzie jest należny. Tak wiele dowiedziałem się o funkcjach okien ze wspaniałej serii na YouTube, a jeden film, w szczególności, zainspirował mnie do następnego przykładu. Należy pamiętać, że przykłady z tej serii są przedstawione z bazą danych niebędącą bazą danych o otwartym kodzie źródłowym system (nie rzucaj we mnie cyfrowymi zgniłymi owocami i warzywami), ogólnie można się wiele nauczyć z filmów.
Widzę wzorzec w większości dotychczasowych wyników zapytania, które chcę zbadać. Nie będę filtrować według miesiąca ani śladu.
To, co chcę wiedzieć, to kolejne dni, w których spaliłem ponad 350 kalorii. Jeszcze lepiej, grupy tamtych dni.
Oto podstawowe zapytanie, od którego zacznę i od którego będę budować:
mysql> SELECT day_walked, burned_calories,
-> ROW_NUMBER() OVER(ORDER BY day_walked ASC) AS positional_bound,
-> trail_hiked
-> FROM vw_fav_shoe_stats
-> WHERE burned_calories > 350;
+------------+-----------------+------------------+------------------------+
| day_walked | burned_calories | positional_bound | trail_hiked |
+------------+-----------------+------------------+------------------------+
| 2018-06-03 | 389.6 | 1 | Sandy Trail-Drive |
| 2018-06-04 | 394.6 | 2 | Sandy Trail-Drive |
| 2018-06-06 | 384.6 | 3 | Sandy Trail-Drive |
| 2018-06-07 | 382.7 | 4 | Sandy Trail-Drive |
| 2018-06-24 | 392.4 | 5 | House-Power Line Route |
| 2018-06-25 | 362.1 | 6 | West Boundary |
| 2018-06-26 | 380.5 | 7 | West Boundary |
| 2018-07-06 | 375.7 | 8 | West Boundary |
| 2018-07-08 | 351.6 | 9 | West Boundary |
| 2018-07-11 | 375.2 | 10 | West Boundary |
| 2018-07-15 | 382.9 | 11 | House-Power Line Route |
| 2018-07-16 | 368.6 | 12 | West Boundary |
| 2018-07-18 | 368.1 | 13 | West Boundary |
| 2018-07-22 | 378.3 | 14 | West Boundary |
| 2018-07-24 | 386.4 | 15 | West Boundary |
| 2018-07-25 | 379.9 | 16 | West Boundary |
| 2018-07-27 | 378.3 | 17 | West Boundary |
| 2018-07-30 | 361.6 | 18 | West Boundary |
| 2018-07-31 | 359.9 | 19 | West Boundary |
| 2018-08-06 | 357.7 | 20 | West Boundary |
+------------+-----------------+------------------+------------------------+
20 rows in set (0.00 sec)
Widzieliśmy już ROW_NUMBER(), ale teraz naprawdę wchodzi w grę.
Aby to zadziałało (przynajmniej w MySQL) musiałem użyć funkcji DATE_SUB(), ponieważ w zasadzie tą techniką odejmujemy liczbę - wartość dostarczoną przez ROW_NUMBER() z kolumny day_walked date tego samego wiersza, która w turn, podaje samą datę poprzez obliczenie:
mysql> SELECT day_walked AS day_of_walk,
-> DATE_SUB(day_walked, INTERVAL ROW_NUMBER() OVER(ORDER BY day_walked ASC) DAY) AS positional_bound,
-> burned_calories,
-> trail_hiked
-> FROM vw_fav_shoe_stats
-> WHERE burned_calories > 350;
+-------------+------------------+-----------------+------------------------+
| day_of_walk | positional_bound | burned_calories | trail_hiked |
+-------------+------------------+-----------------+------------------------+
| 2018-06-03 | 2018-06-02 | 389.6 | Sandy Trail-Drive |
| 2018-06-04 | 2018-06-02 | 394.6 | Sandy Trail-Drive |
| 2018-06-06 | 2018-06-03 | 384.6 | Sandy Trail-Drive |
| 2018-06-07 | 2018-06-03 | 382.7 | Sandy Trail-Drive |
| 2018-06-24 | 2018-06-19 | 392.4 | House-Power Line Route |
| 2018-06-25 | 2018-06-19 | 362.1 | West Boundary |
| 2018-06-26 | 2018-06-19 | 380.5 | West Boundary |
| 2018-07-06 | 2018-06-28 | 375.7 | West Boundary |
| 2018-07-08 | 2018-06-29 | 351.6 | West Boundary |
| 2018-07-11 | 2018-07-01 | 375.2 | West Boundary |
| 2018-07-15 | 2018-07-04 | 382.9 | House-Power Line Route |
| 2018-07-16 | 2018-07-04 | 368.6 | West Boundary |
| 2018-07-18 | 2018-07-05 | 368.1 | West Boundary |
| 2018-07-22 | 2018-07-08 | 378.3 | West Boundary |
| 2018-07-24 | 2018-07-09 | 386.4 | West Boundary |
| 2018-07-25 | 2018-07-09 | 379.9 | West Boundary |
| 2018-07-27 | 2018-07-10 | 378.3 | West Boundary |
| 2018-07-30 | 2018-07-12 | 361.6 | West Boundary |
| 2018-07-31 | 2018-07-12 | 359.9 | West Boundary |
| 2018-08-06 | 2018-07-17 | 357.7 | West Boundary |
+-------------+------------------+-----------------+------------------------+
20 rows in set (0.00 sec)
Jednak bez DATE_SUB() kończysz z tym (a przynajmniej ja):
mysql> SELECT day_walked AS day_of_walk,
-> day_walked - ROW_NUMBER() OVER(ORDER BY day_walked ASC) AS positional_bound,
-> burned_calories,
-> trail_hiked
-> FROM vw_fav_shoe_stats
-> WHERE burned_calories > 350;
+-------------+------------------+-----------------+------------------------+
| day_of_walk | positional_bound | burned_calories | trail_hiked |
+-------------+------------------+-----------------+------------------------+
| 2018-06-03 | 20180602 | 389.6 | Sandy Trail-Drive |
| 2018-06-04 | 20180602 | 394.6 | Sandy Trail-Drive |
| 2018-06-06 | 20180603 | 384.6 | Sandy Trail-Drive |
| 2018-06-07 | 20180603 | 382.7 | Sandy Trail-Drive |
| 2018-06-24 | 20180619 | 392.4 | House-Power Line Route |
| 2018-06-25 | 20180619 | 362.1 | West Boundary |
| 2018-06-26 | 20180619 | 380.5 | West Boundary |
| 2018-07-06 | 20180698 | 375.7 | West Boundary |
| 2018-07-08 | 20180699 | 351.6 | West Boundary |
| 2018-07-11 | 20180701 | 375.2 | West Boundary |
| 2018-07-15 | 20180704 | 382.9 | House-Power Line Route |
| 2018-07-16 | 20180704 | 368.6 | West Boundary |
| 2018-07-18 | 20180705 | 368.1 | West Boundary |
| 2018-07-22 | 20180708 | 378.3 | West Boundary |
| 2018-07-24 | 20180709 | 386.4 | West Boundary |
| 2018-07-25 | 20180709 | 379.9 | West Boundary |
| 2018-07-27 | 20180710 | 378.3 | West Boundary |
| 2018-07-30 | 20180712 | 361.6 | West Boundary |
| 2018-07-31 | 20180712 | 359.9 | West Boundary |
| 2018-08-06 | 20180786 | 357.7 | West Boundary |
+-------------+------------------+-----------------+------------------------+
20 rows in set (0.04 sec)
Hej, to naprawdę nie wygląda tak źle.
Co daje?
Eh, wiersz z wartością pozycyjną '20180698'...
Poczekaj chwilę, to ma obliczyć wartość daty, odejmując liczbę ROW_NUMBER() z kolumny day_of_walk.
Prawidłowo.
Nie wiem jak wy, ale nie znam miesiąca z 98 dniami!
Ale jeśli taki istnieje, przynieś dodatkowe czeki!
Cała zabawa na bok, to oczywiście było niepoprawne i skłoniło mnie (ostatecznie) do użycia DATE_SUB(), która zapewnia poprawny zestaw wyników, a następnie umożliwia uruchomienie tego zapytania:
mysql> SELECT MIN(t.day_of_walk),
-> MAX(t.day_of_walk),
-> COUNT(*) AS num_of_hikes
-> FROM (SELECT day_walked AS day_of_walk,
-> DATE_SUB(day_walked, INTERVAL ROW_NUMBER() OVER(ORDER BY day_walked ASC) DAY) AS positional_bound
-> FROM vw_fav_shoe_stats
-> WHERE burned_calories > 350) AS t
-> GROUP BY t.positional_bound
-> ORDER BY 1;
+--------------------+--------------------+--------------+
| MIN(t.day_of_walk) | MAX(t.day_of_walk) | num_of_hikes |
+--------------------+--------------------+--------------+
| 2018-06-03 | 2018-06-04 | 2 |
| 2018-06-06 | 2018-06-07 | 2 |
| 2018-06-24 | 2018-06-26 | 3 |
| 2018-07-06 | 2018-07-06 | 1 |
| 2018-07-08 | 2018-07-08 | 1 |
| 2018-07-11 | 2018-07-11 | 1 |
| 2018-07-15 | 2018-07-16 | 2 |
| 2018-07-18 | 2018-07-18 | 1 |
| 2018-07-22 | 2018-07-22 | 1 |
| 2018-07-24 | 2018-07-25 | 2 |
| 2018-07-27 | 2018-07-27 | 1 |
| 2018-07-30 | 2018-07-31 | 2 |
| 2018-08-06 | 2018-08-06 | 1 |
+--------------------+--------------------+--------------+
13 rows in set (0.12 sec)
Powiązane zasoby ClusterControl dla MySQL MySQL w 2018 r.:Co jest w wersji 8.0 i inne uwagi Testy porównawcze wydajności MySQL:MySQL 5.7 a MySQL 8.0 Zasadniczo zawinąłem zestaw wyników dostarczony z tego zapytania analitycznego, w formie tabeli pochodnej, i odpytywał go o:datę początkową i końcową, liczbę tego, co oznaczyłem num_of_hikes, a następnie pogrupowałem w kolumnie positional_bound, ostatecznie dostarczając zestawy grup kolejne dni, w których spaliłem ponad 350 kalorii.
Możesz zobaczyć w zakresie dat od 2018-06-24 do 2018-06-26, w wyniku czego 3 kolejne dni spełniają kryteria spalonych kalorii 350 w klauzuli WHERE.
Nieźle, jeśli sam tego nie powiem, ale zdecydowanie jest to płyta, którą chcę spróbować i jak najlepiej!
Wniosek
Funkcje okien są w swoim własnym świecie i lidze. Nawet nie zarysowałem ich powierzchni, pokryłem tylko 3 z nich na „wysokim poziomie ' wprowadzający i być może trywialny sens. Miejmy jednak nadzieję, że w tym poście okaże się, że możesz wyszukiwać całkiem interesujące i potencjalnie wnikliwe dane za pomocą „gołego minimum ' z nich korzystać.
Dziękuję za przeczytanie.