Close Menu
    Trending
    • 3D Printer Breaks Kickstarter Record, Raises Over $46M
    • People are using AI to ‘sit’ with them while they trip on psychedelics
    • Reinforcement Learning in the Age of Modern AI | by @pramodchandrayan | Jul, 2025
    • How This Man Grew His Beverage Side Hustle From $1k a Month to 7 Figures
    • Finding the right tool for the job: Visual Search for 1 Million+ Products | by Elliot Ford | Kingfisher-Technology | Jul, 2025
    • How Smart Entrepreneurs Turn Mid-Year Tax Reviews Into Long-Term Financial Wins
    • Become a Better Data Scientist with These Prompt Engineering Tips and Tricks
    • Meanwhile in Europe: How We Learned to Stop Worrying and Love the AI Angst | by Andreas Maier | Jul, 2025
    AIBS News
    • Home
    • Artificial Intelligence
    • Machine Learning
    • AI Technology
    • Data Science
    • More
      • Technology
      • Business
    AIBS News
    Home»Artificial Intelligence»Scaling Statistics: Incremental Standard Deviation in SQL with dbt | by Yuval Gorchover | Jan, 2025
    Artificial Intelligence

    Scaling Statistics: Incremental Standard Deviation in SQL with dbt | by Yuval Gorchover | Jan, 2025

    Team_AIBS NewsBy Team_AIBS NewsJanuary 1, 2025No Comments7 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Telegram Email
    Share
    Facebook Twitter LinkedIn Pinterest Email


    Why scan yesterday’s knowledge when you’ll be able to increment right now’s?

    Towards Data Science

    Picture by the writer

    SQL aggregation features will be computationally costly when utilized to massive datasets. As datasets develop, recalculating metrics over your entire dataset repeatedly turns into inefficient. To handle this problem, incremental aggregation is usually employed — a way that entails sustaining a earlier state and updating it with new incoming knowledge. Whereas this strategy is simple for aggregations like COUNT or SUM, the query arises: how can or not it’s utilized to extra complicated metrics like commonplace deviation?

    Standard deviation is a statistical metric that measures the extent of variation or dispersion in a variable’s values relative to its imply.
    It’s derived by taking the sq. root of the variance.
    The system for calculating the variance of a pattern is as follows:

    Pattern variance system

    Calculating commonplace deviation will be complicated, because it entails updating each the imply and the sum of squared variations throughout all knowledge factors. Nevertheless, with algebraic manipulation, we are able to derive a system for incremental computation — enabling updates utilizing an present dataset and incorporating new knowledge seamlessly. This strategy avoids recalculating from scratch at any time when new knowledge is added, making the method rather more environment friendly (An in depth derivation is offered on my GitHub).

    Derived pattern variance system

    The system was principally damaged into 3 elements:
    1. The present’s set weighted variance
    2. The brand new set’s weighted variance
    3. The imply distinction variance, accounting for between-group variance.

    This methodology permits incremental variance computation by retaining the COUNT (okay), AVG (µk), and VAR (Sk) of the prevailing set, and mixing them with the COUNT (n), AVG (µn), and VAR (Sn) of the brand new set. Consequently, the up to date commonplace deviation will be calculated effectively with out rescanning your entire dataset.

    Now that we’ve wrapped our heads across the math behind incremental commonplace deviation (or at the least caught the gist of it), let’s dive into the dbt SQL implementation. Within the following instance, we’ll stroll by means of find out how to arrange an incremental mannequin to calculate and replace these statistics for a person’s transaction knowledge.

    Take into account a transactions desk named stg__transactions, which tracks person transactions (occasions). Our purpose is to create a time-static desk, int__user_tx_state, that aggregates the ‘state’ of person transactions. The column particulars for each tables are supplied within the image beneath.

    Picture by the writer

    To make the method environment friendly, we intention to replace the state desk incrementally by combining the brand new incoming transactions knowledge with the prevailing aggregated knowledge (i.e. the present person state). This strategy permits us to calculate the up to date person state with out scanning by means of all historic knowledge.

    Picture by the writer

    The code beneath assumes understanding of some dbt ideas, for those who’re unfamiliar with it, you should still have the ability to perceive the code, though I strongly encourage going by means of dbt’s incremental guide or learn this awesome post.

    We’ll assemble a full dbt SQL step-by-step, aiming to calculate incremental aggregations effectively with out repeatedly scanning your entire desk. The method begins by defining the mannequin as incremental in dbt and utilizing unique_key to replace present rows quite than inserting new ones.

    -- depends_on: {{ ref('stg__transactions') }}
    {{ config(materialized='incremental', unique_key=['USER_ID'], incremental_strategy='merge') }}

    Subsequent, we fetch data from the stg__transactions desk.
    The is_incremental block filters transactions with timestamps later than the newest person replace, successfully together with “solely new transactions”.

    WITH NEW_USER_TX_DATA AS (
    SELECT
    USER_ID,
    TX_ID,
    TX_TIMESTAMP,
    TX_VALUE
    FROM {{ ref('stg__transactions') }}
    {% if is_incremental() %}
    WHERE TX_TIMESTAMP > COALESCE((choose max(UPDATED_AT) from {{ this }}), 0::TIMESTAMP_NTZ)
    {% endif %}
    )

    After retrieving the brand new transaction data, we combination them by person, permitting us to incrementally replace every person’s state within the following CTEs.

    INCREMENTAL_USER_TX_DATA AS (
    SELECT
    USER_ID,
    MAX(TX_TIMESTAMP) AS UPDATED_AT,
    COUNT(TX_VALUE) AS INCREMENTAL_COUNT,
    AVG(TX_VALUE) AS INCREMENTAL_AVG,
    SUM(TX_VALUE) AS INCREMENTAL_SUM,
    COALESCE(STDDEV(TX_VALUE), 0) AS INCREMENTAL_STDDEV,
    FROM
    NEW_USER_TX_DATA
    GROUP BY
    USER_ID
    )

    Now we get to the heavy half the place we have to really calculate the aggregations. Once we’re not in incremental mode (i.e. we don’t have any “state” rows but) we merely choose the brand new aggregations

    NEW_USER_CULMULATIVE_DATA AS (
    SELECT
    NEW_DATA.USER_ID,
    {% if not is_incremental() %}
    NEW_DATA.UPDATED_AT AS UPDATED_AT,
    NEW_DATA.INCREMENTAL_COUNT AS COUNT_TX,
    NEW_DATA.INCREMENTAL_AVG AS AVG_TX,
    NEW_DATA.INCREMENTAL_SUM AS SUM_TX,
    NEW_DATA.INCREMENTAL_STDDEV AS STDDEV_TX
    {% else %}
    ...

    However after we’re in incremental mode, we have to be part of previous knowledge and mix it with the brand new knowledge we created within the INCREMENTAL_USER_TX_DATA CTE based mostly on the system described above.
    We begin by calculating the brand new SUM, COUNT and AVG:

      ...
    {% else %}
    COALESCE(EXISTING_USER_DATA.COUNT_TX, 0) AS _n, -- that is n
    NEW_DATA.INCREMENTAL_COUNT AS _k, -- that is okay
    COALESCE(EXISTING_USER_DATA.SUM_TX, 0) + NEW_DATA.INCREMENTAL_SUM AS NEW_SUM_TX, -- new sum
    COALESCE(EXISTING_USER_DATA.COUNT_TX, 0) + NEW_DATA.INCREMENTAL_COUNT AS NEW_COUNT_TX, -- new rely
    NEW_SUM_TX / NEW_COUNT_TX AS AVG_TX, -- new avg
    ...

    We then calculate the variance system’s three elements

    1. The present weighted variance, which is truncated to 0 if the earlier set consists of 1 or much less gadgets:

        ...
    CASE
    WHEN _n > 1 THEN (((_n - 1) / (NEW_COUNT_TX - 1)) * POWER(COALESCE(EXISTING_USER_DATA.STDDEV_TX, 0), 2))
    ELSE 0
    END AS EXISTING_WEIGHTED_VARIANCE, -- present weighted variance
    ...

    2. The incremental weighted variance in the identical method:

        ...
    CASE
    WHEN _k > 1 THEN (((_k - 1) / (NEW_COUNT_TX - 1)) * POWER(NEW_DATA.INCREMENTAL_STDDEV, 2))
    ELSE 0
    END AS INCREMENTAL_WEIGHTED_VARIANCE, -- incremental weighted variance
    ...

    3. The imply distinction variance, as outlined earlier, together with SQL be part of phrases to incorporate previous knowledge.

        ...
    POWER((COALESCE(EXISTING_USER_DATA.AVG_TX, 0) - NEW_DATA.INCREMENTAL_AVG), 2) AS MEAN_DIFF_SQUARED,
    CASE
    WHEN NEW_COUNT_TX = 1 THEN 0
    ELSE (_n * _k) / (NEW_COUNT_TX * (NEW_COUNT_TX - 1))
    END AS BETWEEN_GROUP_WEIGHT, -- between group weight
    BETWEEN_GROUP_WEIGHT * MEAN_DIFF_SQUARED AS MEAN_DIFF_VARIANCE, -- imply diff variance
    EXISTING_WEIGHTED_VARIANCE + INCREMENTAL_WEIGHTED_VARIANCE + MEAN_DIFF_VARIANCE AS VARIANCE_TX,
    CASE
    WHEN _n = 0 THEN NEW_DATA.INCREMENTAL_STDDEV -- no "previous" knowledge
    WHEN _k = 0 THEN EXISTING_USER_DATA.STDDEV_TX -- no "new" knowledge
    ELSE SQRT(VARIANCE_TX) -- stddev (which is the basis of variance)
    END AS STDDEV_TX,
    NEW_DATA.UPDATED_AT AS UPDATED_AT,
    NEW_SUM_TX AS SUM_TX,
    NEW_COUNT_TX AS COUNT_TX
    {% endif %}
    FROM
    INCREMENTAL_USER_TX_DATA new_data
    {% if is_incremental() %}
    LEFT JOIN
    {{ this }} EXISTING_USER_DATA
    ON
    NEW_DATA.USER_ID = EXISTING_USER_DATA.USER_ID
    {% endif %}
    )

    Lastly, we choose the desk’s columns, accounting for each incremental and non-incremental instances:

    SELECT
    USER_ID,
    UPDATED_AT,
    COUNT_TX,
    SUM_TX,
    AVG_TX,
    STDDEV_TX
    FROM NEW_USER_CULMULATIVE_DATA

    By combining all these steps, we arrive on the remaining SQL mannequin:

    -- depends_on: {{ ref('stg__initial_table') }}
    {{ config(materialized='incremental', unique_key=['USER_ID'], incremental_strategy='merge') }}
    WITH NEW_USER_TX_DATA AS (
    SELECT
    USER_ID,
    TX_ID,
    TX_TIMESTAMP,
    TX_VALUE
    FROM {{ ref('stg__initial_table') }}
    {% if is_incremental() %}
    WHERE TX_TIMESTAMP > COALESCE((choose max(UPDATED_AT) from {{ this }}), 0::TIMESTAMP_NTZ)
    {% endif %}
    ),
    INCREMENTAL_USER_TX_DATA AS (
    SELECT
    USER_ID,
    MAX(TX_TIMESTAMP) AS UPDATED_AT,
    COUNT(TX_VALUE) AS INCREMENTAL_COUNT,
    AVG(TX_VALUE) AS INCREMENTAL_AVG,
    SUM(TX_VALUE) AS INCREMENTAL_SUM,
    COALESCE(STDDEV(TX_VALUE), 0) AS INCREMENTAL_STDDEV,
    FROM
    NEW_USER_TX_DATA
    GROUP BY
    USER_ID
    ),

    NEW_USER_CULMULATIVE_DATA AS (
    SELECT
    NEW_DATA.USER_ID,
    {% if not is_incremental() %}
    NEW_DATA.UPDATED_AT AS UPDATED_AT,
    NEW_DATA.INCREMENTAL_COUNT AS COUNT_TX,
    NEW_DATA.INCREMENTAL_AVG AS AVG_TX,
    NEW_DATA.INCREMENTAL_SUM AS SUM_TX,
    NEW_DATA.INCREMENTAL_STDDEV AS STDDEV_TX
    {% else %}
    COALESCE(EXISTING_USER_DATA.COUNT_TX, 0) AS _n, -- that is n
    NEW_DATA.INCREMENTAL_COUNT AS _k, -- that is okay
    COALESCE(EXISTING_USER_DATA.SUM_TX, 0) + NEW_DATA.INCREMENTAL_SUM AS NEW_SUM_TX, -- new sum
    COALESCE(EXISTING_USER_DATA.COUNT_TX, 0) + NEW_DATA.INCREMENTAL_COUNT AS NEW_COUNT_TX, -- new rely
    NEW_SUM_TX / NEW_COUNT_TX AS AVG_TX, -- new avg
    CASE
    WHEN _n > 1 THEN (((_n - 1) / (NEW_COUNT_TX - 1)) * POWER(COALESCE(EXISTING_USER_DATA.STDDEV_TX, 0), 2))
    ELSE 0
    END AS EXISTING_WEIGHTED_VARIANCE, -- present weighted variance
    CASE
    WHEN _k > 1 THEN (((_k - 1) / (NEW_COUNT_TX - 1)) * POWER(NEW_DATA.INCREMENTAL_STDDEV, 2))
    ELSE 0
    END AS INCREMENTAL_WEIGHTED_VARIANCE, -- incremental weighted variance
    POWER((COALESCE(EXISTING_USER_DATA.AVG_TX, 0) - NEW_DATA.INCREMENTAL_AVG), 2) AS MEAN_DIFF_SQUARED,
    CASE
    WHEN NEW_COUNT_TX = 1 THEN 0
    ELSE (_n * _k) / (NEW_COUNT_TX * (NEW_COUNT_TX - 1))
    END AS BETWEEN_GROUP_WEIGHT, -- between group weight
    BETWEEN_GROUP_WEIGHT * MEAN_DIFF_SQUARED AS MEAN_DIFF_VARIANCE,
    EXISTING_WEIGHTED_VARIANCE + INCREMENTAL_WEIGHTED_VARIANCE + MEAN_DIFF_VARIANCE AS VARIANCE_TX,
    CASE
    WHEN _n = 0 THEN NEW_DATA.INCREMENTAL_STDDEV -- no "previous" knowledge
    WHEN _k = 0 THEN EXISTING_USER_DATA.STDDEV_TX -- no "new" knowledge
    ELSE SQRT(VARIANCE_TX) -- stddev (which is the basis of variance)
    END AS STDDEV_TX,
    NEW_DATA.UPDATED_AT AS UPDATED_AT,
    NEW_SUM_TX AS SUM_TX,
    NEW_COUNT_TX AS COUNT_TX
    {% endif %}
    FROM
    INCREMENTAL_USER_TX_DATA new_data
    {% if is_incremental() %}
    LEFT JOIN
    {{ this }} EXISTING_USER_DATA
    ON
    NEW_DATA.USER_ID = EXISTING_USER_DATA.USER_ID
    {% endif %}
    )

    SELECT
    USER_ID,
    UPDATED_AT,
    COUNT_TX,
    SUM_TX,
    AVG_TX,
    STDDEV_TX
    FROM NEW_USER_CULMULATIVE_DATA

    All through this course of, we demonstrated find out how to deal with each non-incremental and incremental modes successfully, leveraging mathematical strategies to replace metrics like variance and commonplace deviation effectively. By combining historic and new knowledge seamlessly, we achieved an optimized, scalable strategy for real-time knowledge aggregation.

    On this article, we explored the mathematical approach for incrementally calculating commonplace deviation and find out how to implement it utilizing dbt’s incremental fashions. This strategy proves to be extremely environment friendly, enabling the processing of huge datasets with out the necessity to re-scan your entire dataset. In follow, this results in sooner, extra scalable methods that may deal with real-time updates effectively. When you’d like to debate this additional or share your ideas, be at liberty to succeed in out — I’d love to listen to your ideas!



    Source link

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Previous ArticleArchitectures and techniques in Artificial Intelligence (AI) and Deep Learning | by Sai Prabhanj Turaga | Jan, 2025
    Next Article How to Make Your Money Manage Itself and Maintain Your Goals
    Team_AIBS News
    • Website

    Related Posts

    Artificial Intelligence

    Become a Better Data Scientist with These Prompt Engineering Tips and Tricks

    July 1, 2025
    Artificial Intelligence

    Lessons Learned After 6.5 Years Of Machine Learning

    July 1, 2025
    Artificial Intelligence

    Prescriptive Modeling Makes Causal Bets – Whether You Know it or Not!

    June 30, 2025
    Add A Comment
    Leave A Reply Cancel Reply

    Top Posts

    3D Printer Breaks Kickstarter Record, Raises Over $46M

    July 1, 2025

    I Tried Buying a Car Through Amazon: Here Are the Pros, Cons

    December 10, 2024

    Amazon and eBay to pay ‘fair share’ for e-waste recycling

    December 10, 2024

    Artificial Intelligence Concerns & Predictions For 2025

    December 10, 2024

    Barbara Corcoran: Entrepreneurs Must ‘Embrace Change’

    December 10, 2024
    Categories
    • AI Technology
    • Artificial Intelligence
    • Business
    • Data Science
    • Machine Learning
    • Technology
    Most Popular

    SambaNova Reports Fastest DeepSeek-R1 671B with High Efficiency

    February 18, 2025

    Next-Level Productivity Has Arrived with Microsoft Office Home & Business 2024

    January 10, 2025

    Essential Skills for the Modern Data Analyst in 2025

    June 10, 2025
    Our Picks

    3D Printer Breaks Kickstarter Record, Raises Over $46M

    July 1, 2025

    People are using AI to ‘sit’ with them while they trip on psychedelics

    July 1, 2025

    Reinforcement Learning in the Age of Modern AI | by @pramodchandrayan | Jul, 2025

    July 1, 2025
    Categories
    • AI Technology
    • Artificial Intelligence
    • Business
    • Data Science
    • Machine Learning
    • Technology
    • Privacy Policy
    • Disclaimer
    • Terms and Conditions
    • About us
    • Contact us
    Copyright © 2024 Aibsnews.comAll Rights Reserved.

    Type above and press Enter to search. Press Esc to cancel.