You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用LAG函数去除电信手机通信数据中因细微差异产生的重复行

Deduplicating Telco Call Data: Fixing Time Calculations & Efficient Deduplication

Hey Anna, let's tackle your deduplication problem and fix that time calculation error first—then we'll build a robust solution that works even for hundreds of Phone1 numbers.

Why the Time Subtraction Error Happens

The error Operand data type time is invalid for subtract operator makes total sense: SQL Server (I’m assuming you’re using it based on your syntax) doesn’t allow direct subtraction of time values. Instead, you need to use the DATEDIFF() function to calculate the difference between two time values in a specific unit (like seconds, which fits your 2-second threshold).

Fixing Your LAG Function CTE

Your original CTE had two key issues:

  • You were partitioning by Time, which doesn’t group related calls correctly—you should partition by the fields that define a unique call context: Date, Phone1, and Phone2.
  • The time difference calculation used invalid subtraction syntax.

Here’s the corrected version, plus a full deduplication logic that matches your desired output:

WITH CTE_set AS (
    -- Your test data
    SELECT '4/04/2020' as [Date], '7:03:46' as Time, '6123456789' as Phone1, '6987654321'as Phone2, '1' as From_Tower UNION 
    SELECT '4/04/2020' as [Date], '7:03:46' as Time, '6123456789' as Phone1, '6987654321'as Phone2, '' as From_Tower UNION 
    SELECT '4/04/2020' as [Date], '7:03:48' as Time, '6123456789' as Phone1, '6987654321'as Phone2, '5' as From_Tower UNION 
    SELECT '4/04/2020' as [Date], '7:03:48' as Time, '6123456789' as Phone1, '6987654321'as Phone2, ''as From_Tower UNION 
    SELECT '4/04/2020' as [Date], '7:03:48' as Time, '6123456789' as Phone1, '6987654321'as Phone2, '.'as From_Tower UNION 
    SELECT '4/04/2020' as [Date], '7:34:33' as Time, '6123456789' as Phone1, '6987654321'as Phone2,'' as From_Tower UNION 
    SELECT '4/04/2020' as [Date], '7:34:34' as Time, '6123456789' as Phone1, '6987654321'as Phone2,'' as From_Tower UNION 
    SELECT '4/04/2020' as [Date], '7:37:34' as Time, '6123456789' as Phone1, '6987654321'as Phone2,'' as From_Tower UNION 
    SELECT '4/04/2020' as [Date], '7:37:34' as Time, '6123456789' as Phone1, '6987654321'as Phone2 ,'-' as From_Tower
),
CTE_dedup AS (
    SELECT 
        [Date], [Time], [Phone1], [Phone2], [From_Tower],
        -- Calculate time difference from the previous row in the same call group
        DATEDIFF(SECOND, LAG([Time]) OVER (PARTITION BY [Date], Phone1, Phone2 ORDER BY [Time]), [Time]) AS TimeDifference,
        -- Rank rows to prioritize valid data first
        ROW_NUMBER() OVER (
            PARTITION BY [Date], Phone1, Phone2,
                -- Group rows within a 2-second window
                DATEADD(SECOND, (DATEDIFF(SECOND, '00:00:00', [Time]) / 2) * 2, '00:00:00')
            ORDER BY 
                -- Prioritize non-placeholder From_Tower values
                CASE WHEN From_Tower NOT IN ('', '.') THEN 0 ELSE 1 END,
                -- For matching priorities, pick the latest time
                [Time] DESC
        ) AS RowRank
    FROM CTE_set
)
-- Select only the top-ranked (unique) row from each group
SELECT [Date], [Time], [Phone1], [Phone2], [From_Tower]
FROM CTE_dedup
WHERE RowRank = 1
ORDER BY [Date], [Time];

How This Solution Works

Let’s break down the key logic:

  1. Time Window Grouping: The expression DATEADD(SECOND, (DATEDIFF(SECOND, '00:00:00', [Time]) / 2) * 2, '00:00:00') groups all rows that fall within the same 2-second window. This ensures rows with a time difference ≤2 seconds are treated as duplicates.
  2. Row Ranking: The ROW_NUMBER() function ranks rows within each group:
    • First, it prioritizes rows where From_Tower isn’t an empty string or '.' (adjust this list if you have other placeholder values like '-' should be excluded, just update the IN clause).
    • For rows with the same priority, it picks the latest time (matching your desired output for the 7:34:33/34 rows).
  3. Filtering Unique Rows: We only keep rows where RowRank = 1, which gives you one unique row per group.

Handling Large Volumes of Data

This solution scales perfectly for hundreds (or thousands) of Phone1 numbers:

  • The PARTITION BY clause efficiently groups rows by Date, Phone1, and Phone2, so each phone pair’s data is processed independently.
  • Window functions like ROW_NUMBER() and LAG() are optimized in modern SQL databases, so they handle large datasets without performance issues. You don’t need arrays—SQL’s built-in window functions are the right tool here.

Alternative Simplified Approach (For Exact Time Matches)

If you only need to deduplicate rows with exactly the same time (not just within 2 seconds), you can simplify the partitioning:

WITH CTE_set AS (/* Your test data */),
CTE_dedup AS (
    SELECT 
        [Date], [Time], [Phone1], [Phone2], [From_Tower],
        ROW_NUMBER() OVER (
            PARTITION BY [Date], Phone1, Phone2, [Time]
            ORDER BY 
                CASE WHEN From_Tower NOT IN ('', '.') THEN 0 ELSE 1 END,
                [Time] DESC
        ) AS RowRank
    FROM CTE_set
)
SELECT [Date], [Time], [Phone1], [Phone2], [From_Tower]
FROM CTE_dedup
WHERE RowRank = 1
ORDER BY [Date], [Time];

This will produce exactly the 4 rows you’re targeting from your test data.

内容的提问来源于stack exchange,提问作者Anna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 11:22:39