Sql server SQL-如何组合行

Sql server SQL-如何组合行,sql-server,sql-server-2012,Sql Server,Sql Server 2012,下表列出了电话和出席人数。我通过在“通话”和“出勤”表上使用union all,然后使用ID上的行号并按日期排序得到了这个结果 表1: Type | ID | Call/AttendanceDate | RowNum ------------|----|---------------------|-------- Attendance | 12 | 2018-09-16 10:11:00 | 82 Call | 12 | 2018-09-18

下表列出了电话和出席人数。我通过在“通话”和“出勤”表上使用union all,然后使用ID上的行号并按日期排序得到了这个结果

表1:

     Type    | ID | Call/AttendanceDate | RowNum 
 ------------|----|---------------------|-------- 
  Attendance | 12 | 2018-09-16 10:11:00 |     82 
  Call       | 12 | 2018-09-18 14:11:47 |     83 
  Call       | 12 | 2018-10-02 17:26:13 |     84 
  Call       | 12 | 2018-10-05 14:58:31 |     85 
  Attendance | 12 | 2018-10-13 01:41:00 |     86 
  Call       | 12 | 2018-10-13 02:39:12 |     87 
  Call       | 12 | 2018-10-13 04:31:22 |     88 
  Attendance | 12 | 2018-10-13 14:29:00 |     89 
  Call       | 12 | 2018-10-13 14:59:19 |     90 
  Attendance | 12 | 2018-10-15 15:50:00 |     91 
我为此使用的代码是:

WITH CTE1 AS
(
SELECT 'Call' as [Type], ID, CallDate AS Date1 
FROM CallsTable     

UNION ALL

SELECT 'Attendance' as [Type], ID, AttendanceDate AS Date2
FROM AttendanceTable] 
)

,CTE2 AS
(
SELECT [Type], Date1, ID, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Date1 ASC) AS RowNum
FROM CTE1
)

--------------------------------OUTPUT--------------------------------

SELECT a.[Type], a.ID, a.Date1, a.RowNum
FROM CTE2 a
JOIN CTE2 b
    ON a.ID= b.ID
    AND a.RowNum = b.RowNum + 1
WHERE a.ID = '12'
ORDER BY ID, RowNum
我想修改它,使其看起来像下面的输出,这样,无论何时,当一个考勤在一个电话之后,它都应该在同一行中

表2:

  Type | ID |     CallDate     | RowNum |    Type    |  AttendanceDate  | RowNum 
 ------|----|------------------|--------|------------|------------------|-------- 
  NULL | 12 | NULL             | NULL   | Attendance | 16/09/2018 10:11 | 82     
  Call | 12 | 18/09/2018 14:11 | 83     | NULL       | NULL             | NULL   
  Call | 12 | 02/10/2018 17:26 | 84     | NULL       | NULL             | NULL   
  Call | 12 | 05/10/2018 14:58 | 85     | Attendance | 13/10/2018 01:41 | 86     
  Call | 12 | 13/10/2018 02:39 | 87     | NULL       | NULL             | NULL   
  Call | 12 | 13/10/2018 04:31 | 88     | Attendance | 13/10/2018 14:29 | 89     
  Call | 12 | 13/10/2018 14:59 | 90     | Attendance | 15/10/2018 15:50 | 91  

这可能吗?我可以使用什么代码?

您可以使用
APPLY

SELECT C.[Type], C.ID, C.CallDate, C.RowNum,
       (CASE WHEN C2.RowNum - C.RowNum = 1 THEN C2.[TYPE] end) [TYPE],
       (CASE WHEN C2.RowNum - C.RowNum = 1 THEN C2.CallDate end) AttendanceDate,    
       (CASE WHEN C2.RowNum - C.RowNum = 1 THEN C2.RowNum end) RowNum    
FROM CTE2 C OUTER APPLY
     (SELECT TOP (1) C2.*
      FROM CTE2 C2
      WHERE C2.ID = C.ID AND C2.[Type] = 'Attendance' AND C2.RowNum > C.RowNum
      ORDER BY C2.RowNum
     ) C2
WHERE C.ID = 12 AND C.[Type] = 'Call';
使用完全联接

SELECT 
*
FROM 
(SELECT * FROM CTE2 WHERE Type = 'CALL') A
FULL JOIN
(SELECT * FROM CTE2 WHERE Type = 'ATTENDANCE') B
ON A.ID = B.ID AND A.RowNum = B.RowNum - 1

不是很优雅,但对我来说很有用,一个表值函数

alter FUNCTION GetCallActivity()
RETURNS @activityTable TABLE 
(
  call_type     varchar(16),
  call_id       int, 
  call_date     datetime, 
  call_rownum   int,
  atnd_type     varchar(16),
  atnd_id       int, 
  atnd_date     datetime, 
  atnd_rownum   int
)
AS
BEGIN
    -- initialize the return table
    insert into @activityTable
    (call_type, call_id, call_date, call_rownum )
    select a.type, a.id, a.activity_date, a.rownum
    from   stack_calls  a
    where  a.type = 'Call'
    order  by a.activity_date;

    -- match to the attendence recs to the call recs
    update @activityTable
    set    atnd_type     = b.type,
           atnd_id       = b.id,
           atnd_date     = b.activity_date,
           atnd_rownum   = b.rownum
    from   stack_calls     b
    join   @activityTable  a
      on   b.rownum = a.call_rownum + 1
    where  b.type = 'Attendance';      

    -- deal with the edge cases
    insert into @activityTable
    ( atnd_type, atnd_id, atnd_date, atnd_rownum )
    select x.type, 
           x.id, 
           x.activity_date,
           x.rownum
    from 
    (
        select a.type, 
               a.id, 
               a.activity_date,
               a.rownum,
               lag(a.type, 1) over (order by a.activity_date) as prev_type 
        from   stack_calls  a
        where  a.type = 'Attendance'
    ) x
    where x.prev_type is null

    RETURN 
END
GO

您使用的是哪种SQL Server版本?为什么示例数据中没有显示考勤的第一行?这些信息来自哪里?我使用的是SQL Server 2012表2中的第一个考勤行也应该在表1中。抱歉,我忘了复制那本书,谢谢你的编辑。我是新来的。感谢它不会在没有电话的情况下显示出席人数。。。采购订单在输入样本中丢失了一条记录谢谢你的帖子。我认为第一个是最有效的。谢谢你的帮助,谢谢。这完全符合我的要求。谢谢你的帮助。我是这个网站的新手。我投了赞成票并打勾。有没有一个用户投票,以及我可以给你?欢迎这样,没有这样的事情像一个用户投票,但我感谢的意图,我很高兴帮助->谢谢你的帖子。我认为第一个是最有效的。谢谢你的帮助。