Select 行在字段中发生更改并将它们连接到另一个 table

Select rows that where a change has occurred in a field and join them to another table

我有以下两个table:

Table 1
datetime (datetime)
code1 (int)
code2 (int)

Table 2
code2 (int)
description (text)

假设数据示例是:

Table 1

   DateTime                 Code1 Code2
** 14/11/2016 6:55:00 PM    6     21
   14/11/2016 6:56:00 PM    6     21
** 14/11/2016 6:57:00 PM    6     23
** 14/11/2016 6:58:00 PM    6     28
   14/11/2016 6:59:00 PM    6     28
   14/11/2016 7:00:00 PM    6     28
** 14/11/2016 7:01:00 PM    6     22
** 14/11/2016 7:02:00 PM    6     23
   14/11/2016 7:03:00 PM    6     23
   14/11/2016 7:04:00 PM    6     23
** 14/11/2016 7:05:00 PM    6     27
** 14/11/2016 7:06:00 PM    5     8
** 14/11/2016 7:07:00 PM    5     9
   14/11/2016 7:08:00 PM    5     9
** 14/11/2016 7:09:00 PM    5     11
** 14/11/2016 7:10:00 PM    5     12
   14/11/2016 7:11:00 PM    5     12
** 14/11/2016 7:12:00 PM    5     14
** 14/11/2016 7:13:00 PM    5     15
   14/11/2016 7:14:00 PM    5     15
** 14/11/2016 7:15:00 PM    5     17

我想 运行 一个 sql-express-2012 查询,该查询将 return 仅加星标的行,然后将 returned 数据加入描述table 基于 code2 - 产生以下输出 table:

最终输出table

   DateTime                 Code1 Code2 Description
** 14/11/2016 6:55:00 PM    6     21    some text 
** 14/11/2016 6:57:00 PM    6     23    some text 
** 14/11/2016 6:58:00 PM    6     28    some text 
** 14/11/2016 7:01:00 PM    6     22    some text 
** 14/11/2016 7:02:00 PM    6     23    some text 
** 14/11/2016 7:05:00 PM    6     27    some text 
** 14/11/2016 7:06:00 PM    5     8     some text 
** 14/11/2016 7:07:00 PM    5     9     some text 
** 14/11/2016 7:09:00 PM    5     11    some text 
** 14/11/2016 7:10:00 PM    5     12    some text 
** 14/11/2016 7:12:00 PM    5     14    some text 
** 14/11/2016 7:13:00 PM    5     15    some text 
** 14/11/2016 7:15:00 PM    5     17    some text

此致,马克

似乎您想获取每组 code1, code2.

的每个第一行(基于日期时间)

使用row_number解析函数分配数字,然后每组只取第一个:

select
  first_occurence.datetime,
  first_occurence.code1,
  first_occurence.code2,
  table2.description
from (
  select *
  from (
    select
      *,
      row_number() over (partition by code1, code2 order by datetime) as rn
    from table1
    ) table1
  where rn = 1
  ) first_occurence
  join table2 on first_occurence.code2 = table2.code2

再次完成您想要的输出后,上面的内容似乎还不够。我不确定其中的逻辑,但我假设一天中的某个特定时间也会组成该组(在您的示例中 code1 = 6, code2 = 23),因此请添加:

convert(varchar(10), datetime, 103) -- date without time
datepart(hour, datetime) -- only hour

PARTITION BY 子句:

select
  first_occurence.datetime,
  first_occurence.code1,
  first_occurence.code2,
  table2.description
from (
  select *
  from (
    select
      *,
      row_number() over (partition by code1, code2, convert(varchar(10),datetime,103), datepart(hour, datetime) order by datetime) as rn
    from table1
    ) table1
  where rn = 1
  ) first_occurence
  join table2 on first_occurence.code2 = table2.code2

为了 select 只有 Code2 更改的行,您可以对 code2:

进行分区
select DateTime, Code1, Code2 from
(select *, rownumber() over (partition by code2 order by datetime) c from table1 ) t
where c = 1

这是困难的部分,我们可以通过加入 table2:

来扩充它
select t.DateTime, t.Code1, t.Code2, t2.Description from
(select *, rownumber() over (partition by code2 order by datetime) c from table1 ) t
left join table2 t2 on t.code2 = t2.code2
where t.c = 1

您还可以使用LEAD函数:

WITH CteLead AS(
    SELECT *,
        ldCode2 = LEAD(Code2) OVER(PARTITION BY code1 ORDER BY datetime)
    FROM Tbl1
)
SELECT
    datetime, code1, code2, t2.description
FROM CteLead cl
INNER JOIN Table2 t2
    ON t2.code2 = cl.code2
WHERE
    code2 <> ldCode2
    OR ldCode2 IS NULL
ORDER BY datetime;

此答案假定时间列中的粒度固定为一分钟间隔:(它也没有按要求使用 window 函数。)

Select a.*, description
  From #tbl1 As a
  Left Join #tbl1 As b
    On a.datetime = DateAdd(Minute, 1, b.datetime)
    And a.code1 = b.code1 
    And a.code2 = b.code2
  Left Join #tbl2 On a.code2 = #tbl2.code2
  Where b.datetime Is Null;