Jak pobrać pierwszy i ostatni rekord pogrupowanego rekordu w zapytaniu MySQL z funkcjami agregowanymi?
Próbuję pobrać pierwszy i ostatni zapis "zgrupowanego" rekordu.
Dokładniej, robię zapytanie takie jak to
SELECT MIN(low_price), MAX(high_price), open, close
FROM symbols
WHERE date BETWEEN(.. ..)
GROUP BY YEARWEEK(date)
Ale chciałbym zdobyć pierwszą i ostatnią płytę grupy. To może zrobić robiąc mnóstwo żądań, ale mam dość duży stół.
Czy istnieje (niski czas przetwarzania, jeśli to możliwe) sposób, aby to zrobić z MySQL?
4 answers
Chcesz użyć GROUP_CONCAT
i SUBSTRING_INDEX
:
SUBSTRING_INDEX( GROUP_CONCAT(CAST(open AS CHAR) ORDER BY datetime), ',', 1 ) AS open
SUBSTRING_INDEX( GROUP_CONCAT(CAST(close AS CHAR) ORDER BY datetime DESC), ',', 1 ) AS close
Pozwala to uniknąć kosztownych zapytań podrzędnych i uważam, że jest to ogólnie bardziej wydajne dla tego konkretnego problemu.
Sprawdź strony podręcznika dla obu funkcji, aby zrozumieć ich argumenty, lub odwiedź ten artykuł, który zawiera przykład jak wykonać timeframe conversion w MySQL aby uzyskać więcej wyjaśnień.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-15 18:13:19
Spróbuj zacząć od tego... :
Select YearWeek, Date, Min(Low_Price), Max(High_Price)
From
(Select YEARWEEK(date) YearWeek, Date, LowPrice, High_Price
From Symbols S
Where Date BETWEEN(.. ..)
GROUP BY YEARWEEK(date)) Z
Group By YearWeek, Date
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-04 14:30:13
Oto świetne konkretne rozwiązanie tego konkretnego problemu: http://topwebguy.com/first-and-last-in-mysql-a-working-solution / To prawie tak proste, jak używanie FIRST I LAST w MySQL.
Dołączę kod, który faktycznie dostarcza rozwiązania, ale możesz poszukać całego tekstu:
SELECT
word ,
(SELECT a.ip_addr FROM article a
WHERE a.word = article.word
ORDER BY a.updated LIMIT 1) AS first_ip,
(SELECT a.ip_addr FROM article a
WHERE a.word = article.word
ORDER BY a.updated DESC LIMIT 1) AS last_ip
FROM notfound GROUP BY word;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-26 00:10:22
Zakładając, że chcesz mieć ID rekordów z NAJNIŻSZYM low_price i najwyższym high_price, możesz dodać te dwie kolumny do zapytania,
SELECT
(SELECT id ORDER BY low_price ASC LIMIT 1) low_price_id,
(SELECT id ORDER BY high_price DESC LIMIT 1) high_price_id,
MIN(low_price), MAX(high_price), open, close
FROM symbols
WHERE date BETWEEN(.. ..)
GROUP BY YEARWEEK(date)
Jeśli wydajność jest problemem, powinieneś dodać kolumnę dla 'year_week', dodać kilka indeksów pokrycia i podzielić zapytanie na dwie części.
Kolumna 'year_week' jest tylko INT ustawioną na wartość YEARWEEK (date) i aktualizowaną za każdym razem, gdy kolumna 'date' jest aktualizowana. W ten sposób nie musisz przeliczać go dla każdego zapytania i możesz indeksuj.
Nowe indeksy pokrycia powinny wyglądać tak. Zamówienie jest ważne. KEY yw_lp_id (year_week, low_price, id), KEY yw_hp_id (year_week, high_price, id)
Powinieneś użyć tych dwóch zapytań
SELECT
(SELECT id ORDER BY low_price ASC LIMIT 1) low_price_id,
MIN(low_price), open, close
FROM symbols
WHERE year_week BETWEEN(.. ..)
GROUP BY year_week
I
SELECT
(SELECT id ORDER BY high_price DESC LIMIT 1) high_price_id,
MAX(high_price), open, close
FROM symbols
WHERE year_week BETWEEN(.. ..)
GROUP BY year_week
Indeksy pokrywające są całkiem przydatne. Sprawdź to Aby uzyskać więcej szczegółów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-06 05:22:18