SQL Server主从表查询:强制单明细且筛选子表记录数=1
筛选子表记录数为1的主从表关联数据
嘿,我来帮你搞定这个SQL查询需求!你需要连接主表BILL_INFO和子表BILL_INFO_DETAIL,并且只保留那些子表中对应记录数恰好为1的主表数据。基于你已有的基础SQL,我给你提供两种常用的实现方式:
方法1:子查询 + GROUP BY + HAVING
这种方法先通过子查询统计每个主表分组对应的子表记录数,筛选出记录数=1的分组,再和原表关联获取详细数据:
SELECT bi.BILL_NUMBER, bi.BILL_DATE, bid.SERVICE_CODE, bid.SERVICE_FEE, bid.REQUESTED_QUANTITY FROM dbo.BILL_INFO bi INNER JOIN dbo.BILL_INFO_DETAIL bid ON bi.BILL_NUMBER = bid.BILL_NUMBER AND bi.PAY_MODE_ID = bid.PAY_MODE_ID AND bi.CASHIER_ID = bid.CASHIER_ID -- 补全你未写完的连接条件 INNER JOIN ( -- 子查询:统计每个主表分组的子表记录数,筛选出数量为1的 SELECT BILL_NUMBER, PAY_MODE_ID, CASHIER_ID FROM dbo.BILL_INFO_DETAIL GROUP BY BILL_NUMBER, PAY_MODE_ID, CASHIER_ID HAVING COUNT(*) = 1 ) AS detail_counts ON bi.BILL_NUMBER = detail_counts.BILL_NUMBER AND bi.PAY_MODE_ID = detail_counts.PAY_MODE_ID AND bi.CASHIER_ID = detail_counts.CASHIER_ID
说明:
- 子查询
detail_counts负责统计每个主表主键组合(BILL_NUMBER、PAY_MODE_ID、CASHIER_ID)对应的子表记录数,通过HAVING COUNT(*) = 1筛选出符合条件的分组。 - 再将主表、子表和这个统计结果关联,就能得到仅对应子表1条记录的详细数据。
方法2:窗口函数(更简洁高效)
如果你使用的SQL版本支持窗口函数(比如SQL Server 2008及以上),可以用COUNT(*) OVER()来直接计算每个主表分组的子表记录数,然后筛选数量=1的记录:
SELECT BILL_NUMBER, BILL_DATE, SERVICE_CODE, SERVICE_FEE, REQUESTED_QUANTITY FROM ( SELECT bi.BILL_NUMBER, bi.BILL_DATE, bid.SERVICE_CODE, bid.SERVICE_FEE, bid.REQUESTED_QUANTITY, -- 窗口函数:计算当前主表分组下的子表总记录数 COUNT(*) OVER (PARTITION BY bi.BILL_NUMBER, bi.PAY_MODE_ID, bi.CASHIER_ID) AS detail_count FROM dbo.BILL_INFO bi INNER JOIN dbo.BILL_INFO_DETAIL bid ON bi.BILL_NUMBER = bid.BILL_NUMBER AND bi.PAY_MODE_ID = bid.PAY_MODE_ID AND bi.CASHIER_ID = bid.CASHIER_ID -- 补全连接条件 ) AS temp WHERE temp.detail_count = 1
说明:
- 内层查询通过
PARTITION BY按主表的主键组合分组,用COUNT(*) OVER()计算每个分组的子表记录数,命名为detail_count。 - 外层查询直接筛选
detail_count = 1的记录,就能得到目标结果,这种写法不需要额外的关联,代码更简洁。
你可以根据自己的SQL版本和实际表结构(比如补全未写完的CASHIER_xxx连接条件)来选择合适的方法~
内容的提问来源于stack exchange,提问作者DoomerDGR8
相关产品推荐
相关产品推荐

