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

窗口函数Count Distinct替代方案优化求助

问题背景与需求

我们有一张交易明细表DataTable,还有一张TimeSortOrder30表——该表记录了一天中的每个30分钟间隔,包含Hour、Min、CustomDateSort三个字段。CustomDateSort的作用是将门店6点开业时间设为起始值,并按顺序顺延至次日,这也是代码中使用DATEADD减去6小时的原因。

客户单日多次交易的情况很常见,我们需要统计每个30分钟间隔时,当日截至该时段的唯一客户数量。但单日交易数据量可达数亿条,数据集规模极大,尝试过临时表方案和CTE方案,代码均运行数小时仍未完成。由于无法在窗口函数中直接使用DISTINCT,我尝试了以下两种实现代码:

临时表方案

DROP TABLE IF EXISTS #TripPrep;

SELECT
    DATEADD(MINUTE, 30 * (DATEDIFF(MINUTE, 0, StartTime) / 30), 0)               AS IntervalStartTime
   ,CAST(Dateadd(HH,-6,StartTime) AS DATE)                                      AS Date
   ,DATEPART(HH, DATEADD(MINUTE, 30 * (DATEDIFF(MINUTE, 0, StartTime) / 30), 0)) AS I_Hour
   ,DATEPART(MI, DATEADD(MINUTE, 30 * (DATEDIFF(MINUTE, 0, StartTime) / 30), 0)) AS I_Min
   ,Cust_ID
INTO
    #TripPrep
FROM DataTable
WHERE
    StoreID       = 1
    AND StartTime >= '2024-07-09 06:00:00 -05:00';
DROP TABLE IF EXISTS #TripPrepWithSortOrder;

SELECT
    TP.IntervalStartTime
   ,TP.Date
   ,TP.I_Hour
   ,TP.I_Min
   ,TP.Cust_ID
   ,TSO.CustomDateSort
INTO
    #TripPrepWithSortOrder
FROM #TripPrep               AS TP
    JOIN dbo.TimeSortOrder30 AS TSO
        ON TP.I_Hour    = TSO.Hour
           AND TP.I_Min = TSO.Min;
DROP TABLE IF EXISTS #DistinctTrips;

SELECT
    TP1.IntervalStartTime
   ,TP1.Date
   ,TP1.I_Hour
   ,TP1.I_Min
   ,TP1.CustomDateSort
   ,COUNT(DISTINCT TP2.Cust_ID) AS Trips
INTO
    #DistinctTrips
FROM #TripPrepWithSortOrder     AS TP1
    JOIN #TripPrepWithSortOrder AS TP2
        ON TP1.Date               = TP2.Date
           AND TP1.CustomDateSort >= TP2.CustomDateSort
GROUP BY
    TP1.IntervalStartTime
   ,TP1.Date
   ,TP1.I_Hour
   ,TP1.I_Min
   ,TP1.CustomDateSort;

SELECT
    DistinctTrips.IntervalStartTime
   ,DistinctTrips.Date
   ,DistinctTrips.I_Hour
   ,DistinctTrips.I_Min
   ,DistinctTrips.CustomDateSort
   ,DistinctTrips.Trips
FROM #DistinctTrips
ORDER BY
    DistinctTrips.IntervalStartTime;

CTE方案

WITH TripPrep
AS
 (
 SELECT
     DATEADD(MINUTE, 30 * (DATEDIFF(MINUTE, 0, StartTime) / 30), 0)               AS IntervalStartTime
    ,CAST(Dateadd(HH,-6,StartTime) AS DATE)                                      AS "Date"
    ,DATEPART(HH, DATEADD(MINUTE, 30 * (DATEDIFF(MINUTE, 0, StartTime) / 30), 0)) AS I_Hour
    ,DATEPART(MI, DATEADD(MINUTE, 30 * (DATEDIFF(MINUTE, 0, StartTime) / 30), 0)) AS I_Min
    ,Cust_ID
 FROM DataTable
 WHERE
     StoreID     = 1
     AND StartTime >= '2024-07-09 06:00:00 -05:00'
 )
    ,TripPrepWithSortOrder
AS
 (
 SELECT
     TP.IntervalStartTime
    ,TP.[Date]
    ,TP.I_Hour
    ,TP.I_Min
    ,TP.Cust_ID
    ,TSO.CustomDateSort

 FROM TripPrep                AS TP
     JOIN dbo.TimeSortOrder30 AS TSO
         ON TP.I_Hour    = TSO.Hour
            AND TP.I_Min = TSO.Min
 )
    ,DistinctTrips
AS
 (
 SELECT
     TP1.IntervalStartTime
    ,TP1.[Date]
    ,TP1.I_Hour
    ,TP1.I_Min
    ,TP1.CustomDateSort
    ,COUNT(DISTINCT TP2.Cust_ID) AS Trips
 FROM TripPrepWithSortOrder     AS TP1
     JOIN TripPrepWithSortOrder AS TP2
         ON TP1.[Date]         = TP2.[Date]
            AND TP1.CustomDateSort >= TP2.CustomDateSort
 GROUP BY
     TP1.IntervalStartTime
    ,TP1.[Date]
    ,TP1.I_Hour
    ,TP1.I_Min
    ,TP1.CustomDateSort
 )
SELECT
    DistinctTrips.IntervalStartTime
   ,DistinctTrips.[Date]
   ,DistinctTrips.I_Hour
   ,DistinctTrips.I_Min
   ,DistinctTrips.CustomDateSort
   ,DistinctTrips.Trips
FROM DistinctTrips
ORDER BY
    DistinctTrips.IntervalStartTime;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:14:51