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

AdventureWorks2017数据库SQL查询求助:筛选特定年份下单客户

解决AdventureWorks2017的客户订单年份筛选问题

嘿,我来帮你搞定这个查询问题!你遇到的问题其实很常见——用WHERE子句没法直接判断一个客户的跨年份订单情况,因为WHERE是针对单条记录过滤的,没法同时检查一个客户是否存在多个不同年份的订单。咱们换个思路,用分组筛选或者子查询来实现需求。

方法一:用CTE(公共表表达式)分步筛选

这种方法逻辑清晰,先找出符合条件的客户,再统计他们的订单数量:

WITH CustomerOrderYears AS (
    -- 先整理每个客户所有的下单年份(去重,避免同一年多次订单重复统计)
    SELECT 
        CustomerID,
        YEAR(OrderDate) AS OrderYear
    FROM Sales.SalesOrderHeader
    GROUP BY CustomerID, YEAR(OrderDate)
),
QualifiedCustomers AS (
    -- 筛选出同时有2011、2014年订单,且无2012、2013年订单的客户
    SELECT CustomerID
    FROM CustomerOrderYears
    GROUP BY CustomerID
    HAVING 
        -- 存在2011年订单
        SUM(CASE WHEN OrderYear = 2011 THEN 1 ELSE 0 END) > 0
        -- 存在2014年订单
        AND SUM(CASE WHEN OrderYear = 2014 THEN 1 ELSE 0 END) > 0
        -- 完全没有2012、2013年订单
        AND SUM(CASE WHEN OrderYear IN (2012, 2013) THEN 1 ELSE 0 END) = 0
)
-- 统计符合条件的客户在2011、2014年的订单数量
SELECT 
    soh.CustomerID,
    YEAR(soh.OrderDate) AS [year],
    COUNT(soh.SalesOrderID) AS ordersQTY
FROM Sales.SalesOrderHeader soh
JOIN QualifiedCustomers qc ON soh.CustomerID = qc.CustomerID
WHERE YEAR(soh.OrderDate) IN (2011, 2014)
GROUP BY soh.CustomerID, YEAR(soh.OrderDate)
ORDER BY soh.CustomerID, [year];

方法二:用EXISTS/NOT EXISTS直接筛选

这种方式更直观,直接在WHERE子句里通过子查询判断客户的订单年份情况:

SELECT 
    CustomerID,
    YEAR(OrderDate) AS [year],
    COUNT(SalesOrderID) AS ordersQTY
FROM Sales.SalesOrderHeader soh
WHERE 
    -- 只统计2011和2014年的订单
    YEAR(OrderDate) IN (2011, 2014)
    -- 该客户存在2011年订单
    AND EXISTS (
        SELECT 1 FROM Sales.SalesOrderHeader soh2 
        WHERE soh2.CustomerID = soh.CustomerID 
        AND YEAR(soh2.OrderDate) = 2011
    )
    -- 该客户存在2014年订单
    AND EXISTS (
        SELECT 1 FROM Sales.SalesOrderHeader soh2 
        WHERE soh2.CustomerID = soh.CustomerID 
        AND YEAR(soh2.OrderDate) = 2014
    )
    -- 该客户完全没有2012、2013年订单
    AND NOT EXISTS (
        SELECT 1 FROM Sales.SalesOrderHeader soh2 
        WHERE soh2.CustomerID = soh.CustomerID 
        AND YEAR(soh2.OrderDate) IN (2012, 2013)
    )
GROUP BY CustomerID, YEAR(OrderDate)
ORDER BY CustomerID, [year];

为什么WHERE子句单独用不行?

你之前用WHERE没得到正确结果,核心原因是WHERE是对单条记录做过滤——一条订单记录的年份只能是某一年,你没法写出YEAR(OrderDate)=2011 AND YEAR(OrderDate)=2014这种条件(这本身矛盾)。必须先按客户维度聚合,检查他们的所有订单年份集合是否符合要求,再去统计对应年份的订单数。

注意:确保你用的表和字段是AdventureWorks2017的正确值——订单表是Sales.SalesOrderHeader,客户ID字段是CustomerID,订单日期是OrderDate,这些在2017版本里是标准的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:53:42