Question

Je vais représenter graphiquement les données netflow stockées dans une base de données MySQL et j'ai besoin d'un moyen efficace d'obtenir les points de données pertinents. Les enregistrements sont stockés avec la date sous la forme d'un entier pour les secondes depuis l'époque. J'aimerais pouvoir faire quelque chose comme:

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

Y a-t-il un moyen de le faire? ou serait-il plus rapide de le gérer localement en python? même pour une table de 500K lignes?

MODIFIER Mon erreur, l'heure est stockée comme un double non signé au lieu d'un INT. J'utilise actuellement GROUP BY (FLOOR (stime / I)) où I correspond à l'intervalle souhaité.

Était-ce utile?

La solution 5

J'ai utilisé les suggestions des deux réponses et d'un collègue. Le résultat final est le suivant:

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

J'ai aussi essayé la solution d'arrondi, mais les résultats étaient incohérents.

Chance

Autres conseils

Vous pourrez peut-être faire cela en utilisant une division entière. Pas sûr de la performance.

Laissez-moi être votre intervalle souhaité en secondes.

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

Avez-vous essayé ce qui suit? Il suffit de diviser la colonne tyiem par 10 et d’arrondir le résultat.

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

Je ne sais pas si la fonction ROUND () et le regroupement d'appels de fonction fonctionnent dans MySQL, bien que ce qui précède soit en T-SQL.

FLOOR dans le groupe par échoue parfois. il regroupe parfois différents moments sous la forme d'une valeur, par exemple, lorsque vous divisez la valeur avec 3, mais ne fait pas la même chose avec 4, bien que la différence entre ces deux valeurs soit bien supérieure à 3 ou 4, qu'il convient de regrouper deux groupes différents. Mieux vaut le placer sur non signé après le sol, qui fonctionne comme:

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

Le problème:

Parfois GROUP BY FLOOR (UNIX_TIMESTAMP (time_field) / 3) donne moins de groupes que GROUP BY FLOOR (UNIX_TIMESTAMP (time_field) / 4) qui est mathématiquement à ne pas ' t pas possible.

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

Je l'ai fait il y a quelques temps, j'ai donc créé une fonction (avec SQL Server, mais je suppose que c'est à peu près la même chose):

J'ai d'abord créé une fonction scalaire qui me renvoie l'identifiant d'une date en fonction d'un intervalle et d'une partie de date (minute, heure, jour, mois, année):

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

Ensuite, j'ai créé une fonction de table qui me renvoie tous les identifiants d’une plage de dates:

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

Donc, si je veux compter tous les utilisateurs ajoutés pour chaque intervalle de 33 minutes:

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

:

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top