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?

Author: Nikita G., 2009-09-04

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ń.

 51
Author: Joao Costa,
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
 2
Author: Charles Bretana,
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;
 0
Author: webmaster,
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.

 -1
Author: james.c.funk,
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