首页 > 解决方案 > 获取特定年份的产品

问题描述

我想选择一个产品结束日期只有 2018 年的网站。

有些网站有多个产品的结束日期。例如,对于站点 A,对于产品 P1,将有多个结束日期,2018、2019、2020。我想要一个产品结束日期为 2018 的站点

┌──────┬────────┬──────────┐
│ 网站 │产品│ EndDate │
├──────┼────────┼──────────┤
│ A │ P1 │ 2018 │
│ A │ P2 │ 2018 │
│ A │ P1 │ 2019 │
│ B │ P2 │ 2018 │
│ B │ P1 │ 2018 │
│ B │ P2 │ 2019 │
│ A │ P1 │ 2018 │
│ C │ P2 │ 2018 │
│ C │ P1 │ 2019 │
│ C │ P2 │ 2020 │
└──────┴────────┴──────────┘

根据样本数据,我需要的结果是:

第二排,A P2 2018
第 5 行,B P1 2018

我写的查询什么也没给出,我知道这是错误的,但如果你想看看:

select * from utk1
where EndDate not in (Select * from utk1 where EndDate = '2018') 
AND   EndDate not in (Select * from utk1 where EndDate = '2019')

标签: sqlsql-server

解决方案


您的问题不够清楚,因为您在 2018 年询问了带有 EndDate 的产品,并且示例中的 EndDate 列有多个 2018 条目,而在预期结果中您只选择了两个条目而没有提及获得预期输出所需的标准(或记录模式)。换句话说,你给社区一个需要解决的难题(或者我的看法)。

无论如何,从给定的输出中,我想您需要获取 2018 年内列出的网站产品。

因此,(如果我的分析技能仍然有效),从给定的输出中,选择了第二行和第五行,因为它们之前的行是同一年(2018 年)。

如果是这种情况,您可能需要考虑LAG()LEAD()功能,它们将在您的情况下有用。您可以使用这些函数添加一些起点和终点,以便进一步过滤。

在您的示例中,我使用ROW_NUMBER()了函数(为了简单起见)。输出可能因实际数据而异,因此您需要检查并确保输出正确,如果您看到一些不正确的数据,那么 LAG() 或 LEAD() 将是您的解决方案。

这是解决方案ROW_NUMBER()

;WITH CTE AS(
SELECT 
    *,
    ROW_NUMBER() OVER(PARTITION BY [site] ORDER BY [site]) AS RN
FROM YourTable
) 
    SELECT
        [site], 
        product, 
        YEAR(EndDate)
    FROM CTE 
    WHERE 
        YEAR(EndDate) = 2018
    AND RN = 2
    ORDER BY [site]

这是LAG()(获取上一条记录)的解决方案

;WITH CTE AS(
SELECT 
    [site], 
    product,
    EndDate AS StartDate, 
    LAG(EndDate) OVER(PARTITION BY [site] ORDER BY [site]) AS EndDate
FROM YourTable
) 
    SELECT
        [site], 
        product, 
        YEAR(EndDate)
    FROM CTE 
    WHERE 
        YEAR(StartDate)  = 2018
    AND YEAR(EndDate)    = 2018
    ORDER BY [site]

推荐阅读