Postgresql time processing skills, statistics every half day, every week, every month and every 5 minutes

1. Every half day

If there is a created_date in the log_bus_runinfo table of timestamp type, how to count the data before 12:00?

In PostgreSQL, you can use DATE_TRUNCthe function and WHEREclause to count data for a specific time range. The following is a query example, which is used to count the number of records in log_bus_runinfothe table creation date created_dateis earlier than 12:00 noon of the current day:

SELECT COUNT(*) 
FROM log_bus_runinfo 
WHERE DATE_TRUNC('day', created_date) = current_date AND created_date < current_date + interval '12 hours'

The above query uses DATE_TRUNCthe function to created_datetruncate the field to that day (the time part is removed), and then uses WHEREthe clause to select records for the current day of the operation (not the entire history) and the creation date is less than 12:00 noon of this day (ie current_date + interval '12 hours').

Similarly, if the second half of the SQL is processed:

SELECT COUNT(*) 
FROM log_bus_runinfo 
WHERE DATE_TRUNC('day', created_date) = current_date 
AND created_date >= current_date + interval '12 hours'

Two, every week

If there is an odometer count_mileage, the field count_mileage indicates the daily mileage, how to count the kilometers of the previous week?

SELECT
        created_date::DATE-(extract(isodow from created_date::TIMESTAMP)-1||'day')::interval countWeek,
        sum(mileage_count) mileage
        from count_mileage
        GROUP BY created_date::DATE-(extract(isodow from created_date::TIMESTAMP)-1||'day')::"interval"
        order by countWeek
        limit 1

It is used to retrieve date creation and total miles from count_mileage table and group them by college id and weekly count. The following is a line-by-line syntax analysis:

  • select created_date::date-(extract(isodow from created_date::timestamp)-1||'day')::interval countweek,: Select the created_date column to format as given, subtract the date preceding the first day of the week from this (for example, if today is Thursday, subtract 3 days), and set the result to the name countweek new column for .
  • sum(mileage_count) mileage: Calculate the total value of mileage_count and name the result mileage.
  • from count_mileage: Select data from the count_mileage table.
  • where 1=1: This condition has no actual effect and is just a placeholder.
  • group by created_date::date-(extract(isodow from created_date::timestamp)-1||'day')::"interval": Group by date, the same as the above created_date column.
  • order by countweek: Sort in ascending order of the column named countweek.
  • limit 1: Results are returned for up to 1 week.

In summary, this sql query retrieves the total mileage per week for a given condition, sorted by date and count.

How to count the mileage of the last 8 weeks? SQL is:

select
        created_date::DATE-(extract(isodow from created_date::TIMESTAMP)-1||'day')::interval countWeek,
        sum(mileage_count) mileage
        from count_mileage
        GROUP BY created_date::DATE-(extract(isodow from created_date::TIMESTAMP)-1||'day')::"interval"
        order by countWeek
        limit 8

3. Monthly

If there is an odometer count_mileage, the field count_mileage indicates the daily mileage, how to count the monthly kilometers?

SQL:

select distinct to_char(created_date,'yyyy-mm') countMonth ,sum(mileage_count) mileage
        from count_mileage
        where 1=1
        and to_char(created_date,'yyyymm')>to_char((select now() as timestamp)-'6 month'::"interval",'yyyymm')
        group by to_char(created_date,'yyyy-mm')
        order by countMonth

It retrieves date creation and total mileage from the count_mileage table and groups by monthly count. The following is a line-by-line syntax analysis:

  • select distinct to_char(created_date,'yyyy-mm') countmonth: Select the created_date column and format it in year-month format. The distinct keyword is used to remove duplicate rows. If there are multiple date values ​​corresponding to the same year and month, only one will be returned.
  • ,sum(mileage_count) mileage: Calculate the total value of mileage_count and name the result mileage.
  • from count_mileage: Select data from the count_mileage table.
  • where 1=1: This condition has no actual effect and is just a placeholder.
  • and to_char(created_date,'yyyymm')>to_char((select now() as timestamp)-'6 month'::"interval",'yyyymm'): Select only the rows within the last six months, and subtract the time of six months from the current time to obtain the difference date when querying, and convert it into a string in the same format and compare it with the fields in the table to filter out those that meet the conditions record of.
  • group by to_char(created_date,'yyyy-mm'): Group data according to year-month format.
  • order by countmonth: Sort in ascending order of the column named countmonth.

So this sql query retrieves the total monthly mileage for the past 6 months, ordered chronologically.

4. Data every 5 minutes

If there is a table with GPS information, log_bus_driver, which has longitude and latitude fields bus_longitute, bus_latitute, time is created_date, and you want to analyze the information by segment every 5 minutes, how to do it?

 SELECT distinct on (CAST (extract(epoch from date_trunc('second', created_date)) AS integer) / 300) created_date
            ts, CAST (extract(epoch from date_trunc('second', created_date)) AS integer) % 300 as sec,
            bus_longitude, bus_latitude
        from log_bus_drive
        where to_char( created_date, 'yyyyMMdd' ) = '20230428'
        order by CAST (extract(epoch from date_trunc('second', created_date)) AS integer) / 300 asc, created_date asc

The main function of this SQL statement is to select all records whose "created_date" is '20230428' from the "log_bus_drive" table, and aggregate the data according to the time interval of 5 minutes (group by 300 seconds). Here you need to break down the query to better understand what it does:

Here's how each element works:

  • distinct on (CAST (extract(epoch from date_trunc('second', created_date)) AS integer) / 300): Group by 5 minutes and select unique results for each group.

  • created_date ts: This column represents the original created_date field value.

  • CAST(extract(epoch from date_trunc('second', created_date)) AS integer) % 300 as sec: This column displays the seconds from created_date to the 5-minute period, the range is 0-299.

  • bus_longitudeand bus_latitude: These fields contain the longitude and latitude coordinates of the bus.

  • log_bus_drive: Data source table.

  • where to_char( created_date, 'yyyyMMdd' ) = '20230428': Filter out the generated date (created_date) that meets the criteria. Here it is April 28, 2023.

  • ORDER BY CAST (extract(epoch from date_trunc('second', created_date)) AS integer) / 300 asc, created_date asc;: Sort in ascending order based on timestamp (second integer) and creation date.

5. Data statistics for the past seven days

If there is a table count_driver_warn, and you want to count the warning data of the past seven days, how to do it?

select sum(warn_count) warnCount,driver_name driverName
        from count_driver_warn
        where created_date >=CURRENT_DATE- INTERVAL '7 day'
               and driver_name is not null
        group by driver_name
        order by warnCount desc

The main function of this SQL statement is to select all created_date records within 7 days from the "count_driver_warn" table, and group by driver name to calculate the number and type of warnings for each driver, and then sort from high to low according to the number of warnings Sort. Here you need to break down the query to better understand what it does:

Here's how each element works:

  • sum(warn_count) warnCount: Calculate the total number of warnings for each driver.

  • driver_name driverName: The name of the driver included in the data and the date it was collected.

  • count_driver_warn: Data source table.

  • WHERE created_date >= CURRENT_DATE - INTERVAL '7 day' AND driver_name IS NOT NULL: Filter out driver records whose creation date is within 7 days and is not empty. Among them, CURRENT_DATEthe function obtains the current system time, INTERVAL '7 day'which is a time interval, used to represent the last 7 days (from the current date onwards).

  • GROUP BY driver_name: Group the records of all drivers and aggregate the total number of warnings for each driver.

  • ORDER BY warnCount DESC: Sort according to the number of warnings, from high to low according to the largest number of warnings.

6. Data capture in the first few minutes          

SELECT <include refid="Base_Column_List" />
    FROM log_bus_runinfo
    WHERE bus_id = #{busId}
    <if test="beforeMinute !=null">
      and created_date>(now() + ('-'||#{beforeMinute}||' min')::interval)
    </if>
    order by created_date desc
    limit 1

The meaning of each part is as follows:

  • select <include refid="base_column_list" />: Select all fields in the table log_bus_runinfo.
  • from log_bus_runinfo: Query from the table log_bus_runinfo.
  • where bus_id = #{busid}: Limit the rows whose bus_id is equal to the passed parameter busid in the query result.
  • <if test="beforeminute !=null">...</if>: Determine whether screening time is required. If the incoming parameter beforeminute is not null, filtering will be performed; otherwise, no filtering will be performed.
  • and created_date>(now() + ('-'||#{beforeminute}||' min')::interval): If time filtering is performed, only those records whose created_date is greater than the current time minus the minutes represented by the parameter beforeminute are selected.
  • order by created_date desc: Sort in reverse order according to the created_date field (that is, the newest record comes first).
  • limit 1: Returns only the first record as the query result.

Overall, the sql statement is based on a certain bus_id to find its recent travel records, and the time range of the records to be searched can be controlled by the parameter beforeminute.

Guess you like

Origin blog.csdn.net/heweiyabeijing/article/details/130260861