如何识别两个表之间的记录差异?

时间:2011-11-18 12:42:01

标签: sql sql-server sql-server-2005

我有两个问题。第一个查询:

select in_gentime
from in_time_temp
where cardnumber = 'MCL1570'
order by in_gentime

输出是:

2011-10-11 08:06:00.000
2011-10-12 08:35:00.000
2011-10-13 08:21:00.000
2011-10-15 08:21:00.000
2011-10-16 08:21:00.000
2011-10-17 08:21:00.000
2011-10-18 08:21:00.000
2011-10-19 08:21:00.000
2011-10-20 08:21:00.000
2011-10-21 08:21:00.000
2011-10-22 08:21:00.000
2011-10-24 08:21:00.000
2011-10-25 08:21:00.000
2011-10-26 09:00:00.000
2011-10-27 09:00:00.000
2011-10-28 09:00:00.000
2011-10-29 09:00:00.000
2011-10-31 09:00:00.000

第二个问题:

select out_gentime
from out_time_temp
where cardnumber = 'MCL1570'
order by out_gentime

输出是:

2011-10-11 22:02:00.000
2011-10-12 21:14:00.000
2011-10-14 21:59:00.000
2011-10-15 21:59:00.000
2011-10-16 21:59:00.000
2011-10-17 21:59:00.000
2011-10-18 21:59:00.000
2011-10-19 21:59:00.000
2011-10-20 21:59:00.000
2011-10-21 21:59:00.000
2011-10-22 21:59:00.000
2011-10-24 21:59:00.000
2011-10-25 21:59:00.000
2011-10-26 18:15:00.000
2011-10-27 18:15:00.000
2011-10-28 18:15:00.000
2011-10-29 23:15:00.000
2011-10-31 22:15:00.000

我需要识别出现在一个表中而不是另一个表中的DATE值的记录。我想忽略具体的TIME。例如,我想只返回这两条记录:

2011-10-13 08:21:00.000
2011-10-14 21:59:00.000 

如何编写查询来执行此操作?

4 个答案:

答案 0 :(得分:2)

像这样......

select in_gentime as THETIME from in_time_temp where cardnumber = 'MCL1570' 
 and in_gentime not in 
(select out_gentime from out_time_temp where cardnumber = 'MCL1570')
union
select out_gentime  as THETIME from out_time_temp where cardnumber = 'MCL1570'
 and out_gentime not in 
(select in_gentime as THETIME from in_time_temp where cardnumber = 'MCL1570' )
order by THETIME

这应该为您提供两个表格中的所有唯一项目。

答案 1 :(得分:2)

如果您使用FULL OUTER JOIN,则可以将日期列表连接在一起,然后只选择其中一个为NULL的记录:

SELECT COALESCE(i.in_gentime, o.out_gentime)  -- pick first non-null value
FROM in_time_temp i
FULL OUTER JOIN out_time_temp o 
    ON  CAST(CONVERT(varchar(8), i.in_gentime,  112) AS datetime) = 
        CAST(CONVERT(varchar(8), o.out_gentime, 112) AS datetime)
    AND i.cardnumber = o.cardnumber
WHERE (i.in_gentime is null or o.out_gentime IS NULL)
AND   (i.cardnumber = 'MCL1750' OR o.cardnumber = 'MCL1750')

<强>更新即可。 Nathan,这里是完整的测试代码,我不确定你为什么没有得到结果,但是当我运行它时会返回4条记录:

CREATE TABLE in_time_temp  
(
    in_gentime   datetime,
    cardnumber   nvarchar(50)
)
insert into in_time_temp values('2011-10-11 08:06:00.000', 'MCL1750')
insert into in_time_temp values('2011-10-12 08:35:00.000', 'MCL1750')
insert into in_time_temp values('2011-10-13 08:21:00.000', 'MCL1750')
insert into in_time_temp values('2011-10-15 08:21:00.000', 'MCL1750')
insert into in_time_temp values('2011-10-16 08:21:00.000', 'MCL1750')
insert into in_time_temp values('2011-10-17 08:21:00.000', 'MCL1750')


CREATE TABLE out_time_temp
(
    out_gentime    datetime,
    cardnumber   nvarchar(50)
)
insert into out_time_temp values('2011-10-11 22:02:00.000', 'MCL1750')
insert into out_time_temp values('2011-10-12 21:14:00.000', 'MCL1750')
insert into out_time_temp values('2011-10-14 21:59:00.000', 'MCL1750')
insert into out_time_temp values('2011-10-15 21:59:00.000', 'MCL1750')
insert into out_time_temp values('2011-10-16 21:59:00.000', 'MCL1750')
insert into out_time_temp values('2011-10-17 21:59:00.000', 'MCL1750')
insert into out_time_temp values('2011-10-18 21:59:00.000', 'MCL1750')
insert into out_time_temp values('2011-10-19 21:59:00.000', 'MCL1750')


SELECT COALESCE(i.in_gentime, o.out_gentime)  -- pick first non-null value
FROM in_time_temp i
FULL OUTER JOIN out_time_temp o 
    ON  CAST(CONVERT(varchar(8), i.in_gentime,  112) AS datetime) = 
        CAST(CONVERT(varchar(8), o.out_gentime, 112) AS datetime)
    AND i.cardnumber = o.cardnumber
WHERE (i.in_gentime is null or o.out_gentime IS NULL)
AND   (i.cardnumber = 'MCL1750' OR o.cardnumber = 'MCL1750')

输出是:

2011-10-13 08:21:00.000
2011-10-14 21:59:00.000
2011-10-18 21:59:00.000
2011-10-19 21:59:00.000

答案 2 :(得分:1)

这应该为您提供两个表之一的时间:

SELECT CASE
          WHEN in_gentime IS NOT NULL THEN in_gentime
          ELSE out_gentime
       END AS THETIME
FROM in_time_temp AS i
FULL OUTER JOIN out_time_temp AS out ON i.cardnumber = out.cardnumber
   AND i.in_gentime = out.out_gentime
WHERE i.in_gentime IS NULL
   OR out.i_gentime IS NULL
order by in_gentime

如果您只想引用DATE而不是TIME部分,那么答案就在这里(就像JohnD提供的那样,最大的区别在于我使用了CASE和他(可能更有效率)使用COALESCE

SELECT CASE
          WHEN i.in_gentime IS NOT NULL THEN i.in_gentime
          ELSE o.out_gentime
       END AS THETIME
FROM in_time_temp AS i
FULL OUTER JOIN out_time_temp AS o ON i.cardnumber = o.cardnumber
   AND CAST(CONVERT(VARCHAR(8), i.in_gentime, 112) AS DATETIME) =
      CAST(CONVERT(VARCHAR(8), o.out_gentime, 112) AS DATETIME)
WHERE i.in_gentime IS NULL
   OR o.out_gentime IS NULL
order by i.in_gentime

答案 3 :(得分:0)

select in_gentime
from in_time_temp
where cardnumber = 'MCL1570' and
      dateadd(day, datediff(day, 0, in_gentime), 0) not in
        (select dateadd(day, datediff(day, 0, out_gentime), 0)
         from out_time_temp 
         where cardnumber = 'MCL1570')
union all         
select out_gentime
from out_time_temp
where  cardnumber = 'MCL1570' and
      dateadd(day, datediff(day, 0, out_gentime), 0) not in
        (select dateadd(day, datediff(day, 0, in_gentime), 0)
         from in_time_temp 
         where cardnumber = 'MCL1570')