根据前几个月提取不存在的值?

时间:2017-11-19 07:15:51

标签: sql sql-server sql-server-2008

我有tb1

code  Name        sal_month
====  =====       ========
101    john       02/2017
102    mathe      02/2017
103    yara       02/2017
104    sara       02/2017
101    john       03/2017
102    mathe      03/2017
103    yara       03/2017
104    sara       03/2017
101    john       04/2017
103    yara       04/2017

2月份,所有人都获得了3月份的工资 如何根据前几个月提取不存在的值?

结果应该来了

code   sal_month
====   =======
102    04/2017
104    04/2017

提前感谢

5 个答案:

答案 0 :(得分:1)

首先我创建了这个表:

create table #T(code int, sal_month varchar(10))

insert into #T values(101,'2/2017'),(102,'2/2017'),(103,'2/2017'),(104,'2/2017'),
(101,'3/2017'),(102,'3/2017'),(104,'3/2017'),(101,'4/2017'),(103,'4/2017')

其次,我执行了这个查询:

SELECT code, Max(sal_Month)
From #T
Where code not in (select code from #T where  sal_Month = (select Max(sal_Month) from #T))
Group by code

然后我得到了以下结果:

enter image description here

注意:我使用的是SQL SERVER 2012

答案 1 :(得分:0)

我认为你可以计算按id分组的salary_month,类似这样,并选择显示少于3次的行。

select code, count (sal_month) from tb1
group by code
having count (sal_month) < 3

之后,您在代码上加入初始表(只是为了过滤所需的完整行)。

所以最后的查询看起来像他的:

select code, sal_month
from tb1 a
join (select code, count (sal_month) from tb1
group by code
having code < 3) X on a.code = X.code

答案 2 :(得分:0)

这样的事情:

DECLARE @DataSource TABLE
(
    [code] INT
   ,[sal_month] VARCHAR(12)
);

INSERT @DataSource ([code], [sal_month])
VALUES (101, '2/2017')
      ,(102, '2/2017')
      ,(103, '2/2017')
      ,(104, '2/2017')
      ,(101, '3/2017')
      ,(102, '3/2017')
      ,(104, '3/2017')
      ,(101, '4/2017')
      ,(103, '4/2017');

WITH DataSource AS
(
    SELECT *
         ,DENSE_RANK() OVER (ORDER BY [sal_month]) AS [MonthID]
         ,MAX([sal_month]) OVER () AS [MaxMonth]
    FROM @DataSource DS1
)
SELECT DS1.[code]   
      ,DS1.[sal_month]
FROM DataSource DS1
LEFT JOIN DataSource DS2
    ON DS1.[code] = DS2.[code]
    AND DS1.[MonthID] = DS2.[MonthID] - 1
LEFT JOIN DataSource DS3
    ON DS1.[code] = DS3.[code]
    AND DS1.[MonthID] = DS3.[MonthID] + 1
WHERE DS2.[code] IS NULL
    AND DS3.[code] IS NOT NULL
    AND DS1.[sal_month] <> DS1.[MaxMonth];

enter image description here

一些注意事项:

  • 我们需要一种方法对月份进行排序,因为你以非常不实用的方式存储它们并不容易;您没有使用日期/日期时间列,并且您的字符串不是有效日期;另外,你使用的字符串并不好,因为如果你有不同年份的[sal_month],我们将无法对它们进行排序;你应该考虑这个 - 一种选择是使用这种格式:

    201512
    201701
    201702
    201711
    

    通过这种方式,我们可以按字符串排序。

  • 核心中的
  • 我使用ROW_NUMBER并将月份排序为字符串;

  • 这个想法是寻找下个月没有的所有记录,但在前一个记录中有记录;同时,排除了上个月的记录,因为他们不可能在下个月有记录;

答案 3 :(得分:0)

试试这个:

select tb2.code, tb2.sal_month from tb
right join (
select code, sal_month, datepart(month, sal_month) + 1 as next_sal_month from tb) as tb2
on (tb.code = tb2.code and datepart(month, tb.sal_month) = tb2.next_sal_month)
where tb2.next_sal_month < 5 and tb.sal_month is null

在结果集中还有一个额外的记录:代码103在3月份没有收到薪水,但是在2月份收到了薪水,因此它也包括在内。

在这里SQL fiddle,尝试:)

答案 4 :(得分:0)

如果没有关于您的牌桌的更多事实,请创建一个月份的2轴的笛卡儿积。代码,然后左边加入存储的数据。当与每种可能的组合相比时,没有存储数据时,很容易识别缺失的项目。

您可能已经拥有要使用的sal_month和/或代码的主表,如果您确实使用了这些表,但如果没有,您可以使用select distinct动态创建它们,如下所示。

create table tbl1 (code int, sal_month varchar(10))

insert into tbl1 values(101,'2/2017'),(102,'2/2017'),(103,'2/2017'),(104,'2/2017'),
(101,'3/2017'),(102,'3/2017'),(104,'3/2017'),(101,'4/2017'),(103,'4/2017')
     

select c.code, m.sal_month
from ( select distinct sal_month from tbl1 ) m
cross join ( select distinct code from tbl1 ) c
Left join tbl1 t on m.sal_month = t.sal_month and c.code = t.code
Where t.sal_month IS NULL
code | sal_month
---: | :--------
 103 | 3/2017   
 102 | 4/2017   
 104 | 4/2017   

dbfiddle here