如何基于多表数据查询本月过期卡片最多的县?
查询本月过期卡片数量最多的区县
表结构
- Customer表:cnp, customer_no(客户编号), city(城市), county(区县)
- Accounts表:account_number(账户编号), customer_no(客户编号), balance(余额)
- Cards表:card_id(卡片ID), account_number(账户编号), card_number(卡号), exp_date(过期日期)
需求
查询本月过期卡片数量最多的区县(COUNTY)
尝试的SQL语句
SELECT TOP 1 Customer.county, COUNT(Customer.county) AS county_count FROM Customer JOIN Accounts ON Customer.customer_no = Accounts.customer_no JOIN Cards ON Accounts.account_number = Cards.account_number WHERE Cards.exp_date BETWEEN DATEADD(month, -1, GETDATE()) AND GETDATE() GROUP BY Customer.county ORDER BY county_count DESC;
问题分析
原SQL的日期条件逻辑有误:DATEADD(month, -1, GETDATE()) AND GETDATE() 筛选的是过去30天左右的过期卡片,而非当前自然月的过期卡片。比如当前是10月15日,这个条件会包含9月15日-10月15日的卡片,不符合"本月过期"的需求。
另外,用COUNT(Customer.county)统计可能存在误差——如果某条Customer记录的county为空,会被排除在统计外,改用卡片ID统计更准确。
修正后的SQL语句
写法1:精准匹配年月
SELECT TOP 1 c.county, COUNT(cd.card_id) AS expired_card_count FROM Customer c JOIN Accounts a ON c.customer_no = a.customer_no JOIN Cards cd ON a.account_number = cd.account_number WHERE YEAR(cd.exp_date) = YEAR(GETDATE()) AND MONTH(cd.exp_date) = MONTH(GETDATE()) GROUP BY c.county ORDER BY expired_card_count DESC;
写法2:日期范围(索引友好)
如果Cards.exp_date字段建有索引,推荐用日期范围写法,让索引正常生效,提升查询性能:
SELECT TOP 1 c.county, COUNT(cd.card_id) AS expired_card_count FROM Customer c JOIN Accounts a ON c.customer_no = a.customer_no JOIN Cards cd ON a.account_number = cd.account_number WHERE cd.exp_date >= DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1) AND cd.exp_date < DATEADD(month, 1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1)) GROUP BY c.county ORDER BY expired_card_count DESC;
补充说明
- 表别名的使用让SQL更简洁易读
- 用
COUNT(cd.card_id)确保统计的是实际过期的卡片数量,避免因county字段为空导致的统计偏差 - 两种写法都能精准筛选当前自然月内过期的卡片,可根据实际索引情况选择
内容的提问来源于stack exchange,提问作者MeLlmaoEphteban
相关产品推荐
相关产品推荐

