DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Data Engineering
  3. Databases
  4. Three SQL Keywords in QuestDB for Finding Missing Data

Three SQL Keywords in QuestDB for Finding Missing Data

A tutorial of using QuestDB to find missing data

Kovid Rathee user avatar by
Kovid Rathee
·
Jan. 29, 23 · Tutorial
Like (2)
Save
Tweet
Share
2.61K Views

Join the DZone community and get the full member experience.

Join For Free

Whether you are just starting to work with a specific data set or monitoring activities and reports based on existing data sets, one of the first things you need to consider is the quality of the data you’re dealing with. Continuity is one of the most critical factors in gauging the quality of time-series data. Time-series systems usually serve use cases where data needs to be consumed, processed, and acted upon with urgency.

Take the example of a public transport vehicle. For the safety of passengers and the timeliness of the service, vehicles need their various sensors — GPS, proximity sensors, pressure sensors, engine diagnostics sensors, and so on. Continuously using the data from these sensors helps the public transport service guarantee timeliness, safety, and reliability. However, a break in the data coming from these sensors would mean that there’s a problem.

Most data access frameworks, including query languages and importable libraries, allow you to filter and see columns or rows where data is missing. The concept of data continuity and completeness isn’t more relevant anywhere than when you’re talking about time-series data. By definition, time-series data needs to be continuous. However, the granularity of the continuum might differ for different requirements.

When you have to test your data for completeness in a relational database, you often have to write complex SQL queries paired with intermediate or temporary tables to find missing data. In some cases, these queries can be tedious and non-performant. QuestDB is a time-series database that lets you store and consume your data in tabular form, but it’s not what you would call a traditional relational database. To cater to the time-series workloads, QuestDB extends the standard SQL functionalities using SQL extensions. One of these extensions is the SAMPLE BY extension, which allows you to find and deal with missing data with ease.

This tutorial will take you through how to use QuestDB’s SQL extensions to find gaps in your data without any complex queries or overhead.

Dataset

To demonstrate finding gaps in time-series data, we’ll be using the trades dataset, which is readily available on the QuestDB demo website. The trades dataset contains real-time anonymized trades data for Bitcoin and Ethereum in US Dollars from 8th March 2022 till date. Here's the table structure of the trades dataset:

SQL
 
CREATE TABLE ‘trades’ (
symbol SYMBOL capacity 256 CACHE,
side SYMBOL capacity 256 CACHE,
price DOUBLE,
amount DOUBLE,
timestamp TIMESTAMP
) timestamp (timestamp) PARTITION BY DAY;


For more details about the dataset and the process used to ingest data into QuestDB, please see the article ‘Demo of live crypto data streamed with QuestDB and Grafana’. Now that you understand the structure and contents of the trades dataset, let's try to figure out if anything is missing.

Finding Missing Data

Using QuestDB

As mentioned earlier in the article, you can use SQL extensions to find missing data in QuestDB. There are three keywords (or SQL keyphrases) you need to know that are unique to QuestDB:

  • SAMPLE BY allows you to create groups and buckets of data based on time ranges.
  • FILL option allows you to specify a fill behavior when using SAMPLE BY, which, in turn, allows you to perform time-series interpolation on the data.
  • ALIGN TO CALENDAR allows you to align your time buckets to a calendar date based on a timezone or an offset.

You can find missing data using a combination of the aforementioned SQL extensions. First, let’s look at a basic query using these extensions to get a day-on-day count of trades in December till date this year, using the following query:

SQL
 
SELECT timestamp,
       COUNT(*) trades_in_december_2022
  FROM 'trades'
 WHERE timestamp IN '2022–12'
SAMPLE BY 1d
 ALIGN TO CALENDAR;


Running this query gives us the following output when selecting “Draw” in the Chart view:


Note that running such a simple aggregate query on low granularity is possible on any database. It only becomes a problem with other databases when the data is too granular, especially in real-time. Now that it’s clear how to use the SQL extensions you need, let’s move on to our query that finds missing data.

In the query, we’ll find the volume-weighted average price (VWAP) indicator for the trades dataset. The key idea is to get all the timestamps where we don't have data to calculate VWAP for all the Bitcoin trades from the starting date of the dataset till now. In the following query, you can see that the trades are sampled by 1 second using the SAMPLE BY 1s statement:

SQL
 
WITH extract AS (
  SELECT timestamp,
         ROUND(SUM(price * amount) / SUM(amount),2) AS vwap_price,
         ROUND(SUM(amount),2) AS volume
    FROM trades
   WHERE symbol = 'BTC-USD'
     AND timestamp > DATEADD('d', -1, NOW())
  SAMPLE BY 1s
   ALIGN TO CALENDAR)
SELECT timestamp,
       vwap_price,
       volume
  FROM extract
 WHERE vwap_price IS NULL
    OR vwap_price = 0;


However, the query doesn’t result in anything, as shown in the image below:


Why? Because QuestDB won’t return anything if there’s no data for a timestamp or timestamp range based on the SAMPLE BY aggregator. To get the missing data from the results, you will need to use the FILL keyword like this:

SQL
 
SAMPLE BY 1s FILL(NULL);


Using this, you can force-fill all the zero-value records for vwap_price with NULL. The complete query for finding missing data will look something like the following:

SQL
 
WITH extract AS (
 SELECT timestamp,
        ROUND(SUM(price * amount) / SUM(amount),2) AS vwap_price,
        ROUND(SUM(amount),2) AS volume
   FROM trades
  WHERE symbol = 'BTC-USD'
    AND timestamp > DATEADD('d', -1, NOW())
 SAMPLE BY 1s FILL(NULL)
  ALIGN TO CALENDAR)
SELECT timestamp,
       vwap_price,
       volume
  FROM extract
 WHERE vwap_price IS NULL;


When you run the query, you will get all the 1s windows where the data was missing, as shown in the image below:

Again, there is no denying that running one-off, ad-hoc queries that aggregate on lower granularity dimensions, such as 1d or 1m, might not be that hard to do in other databases. However, if you want to keep running these queries at scale, they can create performance issues in your traditional relational database. You can get similar results in other databases if you want to find missing data daily, as shown in the image below:

PostgreSQL

If you had to perform the same operation in a PostgreSQL database, you’d need to run a generate_series() function to generate a bunch of data and then join it with the trades dataset. For the sake of simplicity, let's assume that the timestamp format generated by both systems will be the same. To identify gaps in PostgreSQL, you'll need to write something like this:

PLSQL
 
WITH all_seconds AS (
 SELECT *
   FROM generate_series('2022–12–17 00:00:00', 
                        '2022–12–17 23:59:59',
               INTERVAL '1 second') 
        dummy_timestamp)
SELECT *
  FROM (SELECT s.dummy_timestamp,
               ROUND(SUM(t.price * t.amount) / SUM(t.amount),2) AS vwap_price,
               ROUND(SUM(t.amount),2) AS volume 
          FROM all_seconds AS s
          LEFT JOIN trades AS t
            ON s.dummy_timestamp = t.timestamp
         GROUP BY s.dummy_timestamp)
WHERE t.vwap_price IS NULL;


PostgreSQL has the advantage of having a generator function that supports all kinds of dummy data generation use cases, as you witnessed above. Not all databases have this function. In MySQL, for instance, you’d have to use recursive common table expressions (CTEs) to get the job done. In some other databases, it might be even more troublesome.

How Does Finding Missing Data Help?

Identifying missing data is of utmost importance because it can tremendously impact the accuracy and reliability of every system or person that consumes it. When it comes to time-series databases, many use cases come to mind, especially those that involve edge computing devices and IoT devices, such as sensors and detectors.

Take the example of sensors that send data about critical systems in industrial machinery, such as vibration, vibration, torque, pressure, and so on. Data coming from many of these sensors not only help improve machine efficiency but also helps detect early signs of possible machine failures. In many cases, this data might help improve safety and reliability too. If the continuous stream of time-series data is broken, i.e., the data is missing, the aforementioned benefits of having real-time data go down the drain — and can cause more damage than intended as a lot ride on the reliability of these systems. This is why there’s real value in identifying missing data, and QuestDB makes it super easy.

Conclusion

Continuing our SQL extensions theme, this tutorial walked you through finding missing data using SAMPLE BY, FILL, and ALIGN BY CALENDAR keywords with simple and highly performant queries. This article also explored some benefits of identifying missing data, especially in time-series datasets. Now, it's time for you to give this a shot. There's a system ready for you on the demo website. Take it for a ride!

Database Data (computing) sql

Published at DZone with permission of Kovid Rathee. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • DevOps for Developers: Continuous Integration, GitHub Actions, and Sonar Cloud
  • How To Choose the Right Streaming Database
  • Top 5 Data Streaming Trends for 2023
  • What Is Advertised Kafka Address?

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: