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

T-SQL技术问题:统计左连接左表行数及左连接去重实现

T-SQL问题解答

问题1:如何统计左连接中左表T1的行数?

左连接的特性是会保留左表T1的所有行,不管右表T2有没有匹配的数据,所以统计T1的行数分两种场景来处理:

  • 如果想在查询结果的每一行都带上T1的总行数:
    可以用窗口函数 COUNT(T1.EMAIL) OVER (),它会直接计算T1的所有行数(因为你的T1是用UNION拼接的,本身已经去重了,所以COUNT的结果就是唯一邮箱的数量)。把它加到你的查询里就行:

    SELECT 
      T1.EMAIL,
      T2.BILLG_STATE_CD,
      T2.BILLG_ZIP_CD,
      T2.ord_creatd_dt,
      COUNT(T1.EMAIL) OVER () AS T1_Total_Rows -- 新增这行统计左表总行数
    FROM (SELECT EMAIL FROM SJ_FPQ_Q1_19 
          UNION SELECT EMAIL FROM SJ_FPQ_Q2 
          UNION SELECT email AS EMAIL FROM Amber_10182019) AS T1 
    LEFT JOIN ORD_MSTR As T2 ON T1.EMAIL = T2.EMAIL_ADDR 
    WHERE T2.ord_creatd_dt > DATE '2018-01-01' AND T2.ord_creatd_dt < DATE '2019-11-08'
    
  • 如果只是单纯想得到T1的总行数(不需要和连接结果一起返回):
    直接查询T1的记录数就可以,简单直接:

    SELECT COUNT(*) AS T1_Total_Rows
    FROM (SELECT EMAIL FROM SJ_FPQ_Q1_19 
          UNION SELECT EMAIL FROM SJ_FPQ_Q2 
          UNION SELECT email AS EMAIL FROM Amber_10182019) AS T1
    

问题2:每个T1邮箱仅返回一条结果,处理T2的重复数据

你提到的PARTITION BY思路完全正确,只是可能没找对语法位置。这里核心是先给T2中每个邮箱的记录做排序标记,只保留最新的那一条,再和T1做连接。我给你两种可靠的实现方式:

方式1:用ROW_NUMBER()窗口函数(推荐,灵活处理多重复场景)

这种方法可以精准控制取哪一条记录,比如最新订单,或者最大订单ID的记录:

SELECT 
  T1.EMAIL,
  T2_filtered.BILLG_STATE_CD,
  T2_filtered.BILLG_ZIP_CD,
  T2_filtered.ord_creatd_dt
FROM (
  SELECT EMAIL FROM SJ_FPQ_Q1_19 
  UNION SELECT EMAIL FROM SJ_FPQ_Q2 
  UNION SELECT email AS EMAIL FROM Amber_10182019
) AS T1 
LEFT JOIN (
  SELECT 
    EMAIL_ADDR,
    BILLG_STATE_CD,
    BILLG_ZIP_CD,
    ord_creatd_dt,
    -- 按邮箱分组,组内按订单日期降序排,最新的记录会被标记为1
    ROW_NUMBER() OVER (PARTITION BY EMAIL_ADDR ORDER BY ord_creatd_dt DESC) AS row_num
  FROM ORD_MSTR
  WHERE ord_creatd_dt > DATE '2018-01-01' AND ord_creatd_dt < DATE '2019-11-08'
) AS T2_filtered ON T1.EMAIL = T2_filtered.EMAIL_ADDR
-- 只保留每个邮箱的第一条记录,同时保留T1中无匹配的邮箱
WHERE T2_filtered.row_num = 1 OR T2_filtered.row_num IS NULL

如果遇到同一个邮箱同一天有多个订单的情况,你可以在ORDER BY里再加一个排序字段,比如ORDER BY ord_creatd_dt DESC, ORD_ID DESC,确保只取唯一的一条。

方式2:用MAX(ord_creatd_dt)关联

如果你更倾向于用MAX日期的方式,也可以先找出每个邮箱的最新订单日期,再回表关联T2获取地址信息:

SELECT 
  T1.EMAIL,
  T2.BILLG_STATE_CD,
  T2.BILLG_ZIP_CD,
  T2.ord_creatd_dt
FROM (
  SELECT EMAIL FROM SJ_FPQ_Q1_19 
  UNION SELECT EMAIL FROM SJ_FPQ_Q2 
  UNION SELECT email AS EMAIL FROM Amber_10182019
) AS T1 
LEFT JOIN (
  -- 先获取每个邮箱的最新订单日期
  SELECT EMAIL_ADDR, MAX(ord_creatd_dt) AS latest_dt
  FROM ORD_MSTR
  WHERE ord_creatd_dt > DATE '2018-01-01' AND ord_creatd_dt < DATE '2019-11-08'
  GROUP BY EMAIL_ADDR
) AS T2_max ON T1.EMAIL = T2_max.EMAIL_ADDR
-- 关联回T2拿到对应的地址数据
LEFT JOIN ORD_MSTR AS T2 ON T2_max.EMAIL_ADDR = T2.EMAIL_ADDR AND T2_max.latest_dt = T2.ord_creatd_dt

不过这种方法要注意,如果同一个邮箱在latest_dt当天有多个订单,还是会返回多条记录,这时候就需要额外的过滤条件,或者改用第一种方式更稳妥。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:42:38