MySQL group by-Intervallen in einem Datumsbereich
Frage
Ich bin Grafik-netflow-Daten in eine MySQL-Datenbank, und ich muss einen effizienten Weg, um die relevanten Daten Punkte.Diese Datensätze gespeichert sind, mit dem Datum als int für Sekunden seit der Epoche.Ich Möchte in der Lage sein, etwas wie:
Select SUM(bytes) from table where stime > x and stime < Y
group by (10 second intervals)
Gibt es trotzdem, dies zu tun?oder, wäre es schneller zu handhaben es vor Ort in python?auch für 500K Zeile der Tabelle?
BEARBEITEN
Mein Fehler, die Zeit wird gespeichert als unsigned double statt INT.Ich bin derzeit mit GROUP BY (FLOOR(stime / I))
wo ich das gewünschte Intervall.
Lösung 5
Ich verwendet Anregungen aus beiden Antworten und ein Mitarbeiter.End-Ergebnis ist wie folgt:
Select FROM_UNIXTIME(stime), bytes
from argusTable_2009_10_22
where stime > (UNIX_TIMESTAMP()-600)
group by floor(stime /10)
Ich habe versucht, die Rundung Lösung, aber die Ergebnisse waren inkonsistent.
Chance
Andere Tipps
Sie können möglicherweise diese mit Integer-Division tun. Nicht sicher, ob der Leistung.
Lassen Sie mich Ihnen gewünschtes Intervall in Sekunden.
SELECT SUM(bytes), ((stime - X) DIV I) as interval
FROM table
WHERE (stime > X) and (stime < Y)
GROUP BY interval
Example, let X = 1500 and I = 10
stime = 1503 -> (1503 - 1500) DIV 10 = 0
stime = 1507 -> (1507 - 1500) DIV 10 = 0
stime = 1514 -> (1514 - 1500) DIV 10 = 1
stime = 1523 -> (1523 - 1500) DIV 10 = 2
Haben Sie versucht, die folgenden? devide einfach die tyiem Säule um 10 und um das Ergebnis nach unten.
SELECT SUM(bytes)
FROM table
WHERE stime > x
AND stime < Y
GROUP BY ROUND(stime/10, -1)
Ich weiß nicht, ob die Funktion ROUND () und mit der Funktion Gruppierung ruft Werke in MySQL aber die oben ist T-SQL.
FLOOR
in Gruppe manchmal versagt. es manchmal Gruppen unterschiedliche Zeiten als ein Wert zum Beispiel, wenn Sie den Wert mit 3 teilen, aber es tut nicht das gleiche, wenn Sie mit 4 teilen, obwohl die Differenz zwischen diesen beiden Werten weit größer als 3 oder 4 ist, die es Gruppe sollte als zwei verschiedene Gruppen. Besser wirft es in unsigned nach Etage, die funktioniert wie:
CAST(FLOOR(UNIX_TIMESTAMP(time_field)/I) AS UNSIGNED INT)
Das Problem:
Manchmal gibt GROUP BY FLOOR(UNIX_TIMESTAMP(time_field)/3)
weniger Gruppen im Vergleich zu GROUP BY FLOOR(UNIX_TIMESTAMP(time_field)/4)
die mathematisch nicht möglich sein sollte.
SELECT sec_to_time(time_to_sec(datefield)- time_to_sec(datefield)%(10)) as intervals,SUM(bytes)
FROM table
WHERE where stime > x and stime < Y
group by intervals
Ich tat dies ein paar Mal vor, so erstellt ich eine Funktion (mit SQL-Server, aber ich nehme an, es ist fast das gleiche):
Zuerst habe ich eine skalare Funktion, die mir die ID eines Datums Rückkehr in Abhängigkeit von einem Intervall und einem Datumsteil (Minute, Stunde, Tag, Nachtfalter, Jahr):
CREATE FUNCTION [dbo].[GetIDDate]
(
@date datetime,
@part nvarchar(10),
@intervalle int
)
RETURNS int
AS
BEGIN
-- Declare the return variable here
DECLARE @res int
DECLARE @date_base datetime
SET @date_base = convert(datetime,'01/01/1970',103)
set @res = case @part
WHEN 'minute' THEN datediff(minute,@date_base,@date)/@intervalle
WHEN 'hour' THEN datediff(hour,@date_base,@date)/@intervalle
WHEN 'day' THEN datediff(day,@date_base,@date)/@intervalle
WHEN 'month' THEN datediff(month,@date_base,@date)/@intervalle
WHEN 'year' THEN datediff(year,@date_base,@date)/@intervalle
ELSE datediff(minute,@date_base,@date)/@intervalle END
-- Return the result of the function
RETURN @res
END
Dann habe ich eine Tabellenfunktion, die mir alle id betweend Datumsbereich zurückgibt:
CREATE FUNCTION [dbo].[GetTableDate]
(
-- Add the parameters for the function here
@start_date datetime,
@end_date datetime,
@interval int,
@unite varchar(10)
)
RETURNS @res TABLE (StartDate datetime,TxtStartDate nvarchar(50),EndDate datetime,TxtEndDate nvarchar(50),IdDate int)
AS
begin
declare @current_date datetime
declare @end_date_courante datetime
declare @txt_start_date nvarchar(50)
declare @txt_end_date nvarchar(50)
set @current_date = case @unite
WHEN 'minute' THEN dateadd(minute, datediff(minute,0,@start_date),0)
WHEN 'hour' THEN dateadd(hour, datediff(hour,0,@start_date),0)
WHEN 'day' THEN dateadd(day, datediff(day,0,@start_date),0)
WHEN 'month' THEN dateadd(month, datediff(month,0,@start_date),0)
WHEN 'year' THEN dateadd(year, datediff(year,0,dateadd(year,@interval,@start_date)),0)
ELSE dateadd(minute, datediff(minute,0,@start_date),0) END
while @current_date < @end_date
begin
set @end_date_courante =
case @unite
WHEN 'minute' THEN dateadd(minute, datediff(minute,0,dateadd(minute,@interval,@current_date)),0)
WHEN 'hour' THEN dateadd(hour, datediff(hour,0,dateadd(hour,@interval,@current_date)),0)
WHEN 'day' THEN dateadd(day, datediff(day,0,dateadd(day,@interval,@current_date)),0)
WHEN 'month' THEN dateadd(month, datediff(month,0,dateadd(month,@interval,@current_date)),0)
WHEN 'year' THEN dateadd(year, datediff(year,0,dateadd(year,@interval,@current_date)),0)
ELSE dateadd(minute, datediff(minute,0,dateadd(minute,@interval,@current_date)),0) END
SET @txt_start_date = case @unite
WHEN 'minute' THEN CONVERT(VARCHAR(20), @current_date, 100)
WHEN 'hour' THEN CONVERT(VARCHAR(20), @current_date, 100)
WHEN 'day' THEN REPLACE(CONVERT(VARCHAR(11), @current_date, 106), ' ', '-')
WHEN 'month' THEN REPLACE(RIGHT(CONVERT(VARCHAR(11), @current_date, 106), 8), ' ', '-')
WHEN 'year' THEN CONVERT(VARCHAR(20), datepart(year,@current_date))
ELSE CONVERT(VARCHAR(20), @current_date, 100) END
SET @txt_end_date = case @unite
WHEN 'minute' THEN CONVERT(VARCHAR(20), @end_date_courante, 100)
WHEN 'hour' THEN CONVERT(VARCHAR(20), @end_date_courante, 100)
WHEN 'day' THEN REPLACE(CONVERT(VARCHAR(11), @end_date_courante, 106), ' ', '-')
WHEN 'month' THEN REPLACE(RIGHT(CONVERT(VARCHAR(11), @end_date_courante, 106), 8), ' ', '-')
WHEN 'year' THEN CONVERT(VARCHAR(20), datepart(year,@end_date_courante))
ELSE CONVERT(VARCHAR(20), @end_date_courante, 100) END
INSERT INTO @res (
StartDate,
EndDate,
TxtStartDate,
TxtEndDate,
IdDate) values(
@current_date,
@end_date_courante,
@txt_start_date,
@txt_end_date,
dbo.GetIDDate(@current_date,@unite,@interval)
)
set @current_date = @end_date_courante
end
return
end
Also, wenn ich möchte das alle Benutzer für jedes Intervall von 33 Minuten gegeben zählen:
SELECT count(id_user) , timeTable.StartDate
FROM user
INNER JOIn dbo.[GetTableDate]('1970-01-01',datedate(),33,'minute') as timeTable
ON dbo.getIDDate(user.creation_date,'minute',33) = timeTable.IDDate
GROUP BY dbo.getIDDate (user.creation_date, 'Minute', 33) ORDER BY timeTable.StartDate
:)