获取特定年份的产品

时间:2018-06-16 14:21:53

标签: sql sql-server

我想选择产品结束日期仅为2018年的网站。

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

┌──────┬───────┬─────────┐
│ site │product│ 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  │
└──────┴───────┴─────────┘

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

2nd row, A  P2  2018
5th row, 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')

6 个答案:

答案 0 :(得分:1)

你的方法没问题。您只需要正确的in逻辑:

select *
from utk1
where site in (Select site from utk1 where EndDate = '2018')  and
      site not in (Select site from utk1 where EndDate >= '2019');

注意:我并不相信你将岁月存储为字符串。所以,你应该省去单引号。混合类型是一种不好的做法。 (如果值确实是字符串,请在下面添加单引号。)

如果您想在产品级别使用此功能,请使用exists

select u.*
from utk1
where not exists (select 1
                  from utk1 u2 
                  where u2.site = u.site and u2.product = u.product and
                        u2.enddate >= 2019
                 ) and
      exists (select 1
              from utk1 u2 
              where u2.site = u.site and u2.product = u.product and
                    u2.enddate = 2018
             ) ;

但是,我认为更好的方法是聚合:

select site, product
from utk1
group by site, product
having max(enddate) = 2018;

这将为您提供2018年结束的site / product对。根据评论,这似乎是对该问题最合理的解释。

答案 1 :(得分:1)

您的问题不够明确,因为您在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]

答案 2 :(得分:0)

您可以尝试以下

WITH cte (site, product, enddate) 
AS (
    SELECT site, product, MAX(enddate)
    FROM utk1
    GROUP BY site, product
)
SELECT site, product, enddate
FROM cte
WHERE enddate = 2018

修改

正在为每个网站和产品组合创建一个/ cte集,其最大结束日期。之后只考虑结束2018年的那些 例如。对于站点B产品P1,最大/最高结束日期是2019,这导致不考虑该行。对于站点B P2,最大结束日期是2018年,因此该行是endresult的一部分。

答案 3 :(得分:0)

如果您想要的产品仅在2018年,而不是其他年份,则需要将计数条件添加为1:

SELECT site, product, MAX(EndDate) AS EndDate
FROM utk1
GROUP BY site, product
HAVING MAX(EndDate) = '2018'
   AND COUNT(DISTINCT EndDate) = 1;

注意:从您的问题来看,EndDate似乎是varchar。如果这不正确并且是一个数字,请将= '2018'更改为= 2018(删除引号)。此答案也假设在2018年之前可能有几年。如果情况并非如此,那么最后一行不是必需的,可以删除。

答案 4 :(得分:0)

你应该尝试这个

Select * from (
SELECT site, product, MAX(enddate) as enddate
FROM utk1 
GROUP BY site, product
)a where enddate = '2018'

答案 5 :(得分:-1)

select * from utk1
group by site,product
having max(EndDate) ='2018';