Domanda

Sto per rappresentare graficamente i dati di netflow memorizzati in un database MySQL e ho bisogno di un modo efficiente per ottenere i punti dati rilevanti. I loro record sono memorizzati con la data come int per secondi dall'epoca. Vorrei poter fare qualcosa del genere:

Select SUM(bytes) from table where stime > x and stime < Y  
group by (10 second intervals)

Esiste un modo per farlo? o sarebbe più veloce gestirlo localmente in Python? anche per una tabella di righe da 500 KB?

Modifica Errore mio, il tempo viene memorizzato come doppio non firmato anziché come INT. Attualmente sto usando GROUP BY (FLOOR (stime / I)) dove sono l'intervallo desiderato.

È stato utile?

Soluzione 5

Ho usato suggerimenti di entrambe le risposte e di un collega. Il risultato finale è il seguente:

Select FROM_UNIXTIME(stime), bytes 
from argusTable_2009_10_22 
where stime > (UNIX_TIMESTAMP()-600)
group by floor(stime /10)

Ho provato anche la soluzione di arrotondamento, ma i risultati non erano coerenti.

Chance

Altri suggerimenti

Potresti essere in grado di farlo usando la divisione intera. Non sono sicuro della prestazione.

Lascia che io sia l'intervallo desiderato in secondi.

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

Hai provato quanto segue? Basta dividere la colonna tyiem per 10 e arrotondare il risultato verso il basso.

SELECT    SUM(bytes) 
FROM      table 
WHERE     stime > x 
AND       stime < Y
GROUP BY  ROUND(stime/10, -1)

Non so se la funzione ROUND () e il raggruppamento con le chiamate di funzione funzionino in MySQL, ma quanto sopra è T-SQL.

FLOOR nel gruppo a volte fallisce. a volte raggruppa tempi diversi come un valore, ad esempio quando dividi il valore con 3, ma non fa lo stesso quando dividi con 4, anche se la differenza tra questi due valori è molto maggiore di 3 o 4 che dovrebbe raggruppare come due gruppi diversi. Meglio lanciarlo su unsigned after floor che funziona come:

CAST(FLOOR(UNIX_TIMESTAMP(time_field)/I) AS UNSIGNED INT)

Il problema:

A volte GROUP BY FLOOR (UNIX_TIMESTAMP (time_field) / 3) offre meno gruppi rispetto a GROUP BY FLOOR (UNIX_TIMESTAMP (time_field) / 4) che matematicamente non dovrebbe ' essere possibile.

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

L'ho fatto qualche tempo fa, quindi ho creato alcune funzioni (con SQL Server, ma suppongo che sia quasi lo stesso):

Per prima cosa ho creato una funzione scalare che mi restituisce l'ID di una data in base a un intervallo e una parte della data (minuti, ora, giorno, falena, anno):

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

Quindi ho creato una funzione di tabella che mi restituisce tutti gli ID tra un intervallo di date:

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

Quindi, se voglio contare tutto l'utente aggiunto per ogni intervallo di 33 minuti:

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) ORDINA PER timeTable.StartDate

:)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top