Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何获取在同一表的连续行中具有不同值的列的名称和值_Sql_Sql Server_Tsql - Fatal编程技术网

Sql 如何获取在同一表的连续行中具有不同值的列的名称和值

Sql 如何获取在同一表的连续行中具有不同值的列的名称和值,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有一个包含以下列的表历史记录: HistoryId---User---Tag---Updateddate----DeptId 1 B12 abc 10-08-2017 D34 2 B24 abc 11-08-2017 D34 3 B24 def 12-08-2017 D34 我有一个问题 SELECT * FROM History WHERE DeptId = 'D34

我有一个包含以下列的表历史记录:

HistoryId---User---Tag---Updateddate----DeptId
1           B12    abc   10-08-2017      D34
2           B24    abc   11-08-2017      D34
3           B24    def   12-08-2017      D34
我有一个问题

SELECT
  *
FROM History
WHERE DeptId = 'D34'
ORDER BY Updateddate
这个查询的结果给出了上面3行。 现在,在这些行中,我需要连续行中具有不同值的列的名称和值

比如:

HistoryId-----Column-----Value
2             User       B24
3             Tag        def

有什么方法可以做到这一点吗?

如果标签或用户没有空值,那么可以通过使用滞后和交叉应用的组合来检查是否有任何值不同

SELECT H.HistoryID, C.Col, C.Val
FROM (
    SELECT *, PrevUser = LAG([User]) OVER (ORDER BY HistoryID), PrevTag = LAG([Tag]) OVER (ORDER BY HistoryID)
    FROM [History] AS H
) AS H
CROSS APPLY (
    VALUES
        ('User', CASE WHEN PrevUser != [User] THEN [User] END),
        ('Tag', CASE WHEN PrevTag != Tag THEN Tag END)
) AS C(Col, Val)
WHERE C.Val IS NOT NULL;
如果有空值,它会变得有点复杂,但基本思想是一样的,您只需要添加规则来检查空值并忽略第一行

编辑:如果你也需要检查空值,一种方法是如下所示

DECLARE @History TABLE (HistoryID INT, [User] CHAR(3), [Tag] CHAR(3));
INSERT @History VALUES 
    (1,'B12','abc'),
    (2,'B24','abc'),
    (3,'B24','def'),
    (4,NULL,'def'),
    (5,'A24',NULL),
    (6,NULL,NULL),
    (7,'123','456');

SELECT H.HistoryID, C.Col, C.Val
FROM (
    SELECT *, RN = ROW_NUMBER() OVER (ORDER BY HistoryID), PrevUser = LAG([User]) OVER (ORDER BY HistoryID), PrevTag = LAG([Tag]) OVER (ORDER BY HistoryID)
    FROM @History AS H
) AS H
CROSS APPLY (
    VALUES
        ('User', CASE WHEN RN != 1 AND (PrevUser != [User] OR (PrevUser IS NULL AND [User] IS NOT NULL) OR (PrevUser IS NOT NULL AND [User] IS NULL)) THEN [User] END, CASE WHEN RN != 1 AND (PrevUser != [User] OR (PrevUser IS NULL AND [User] IS NOT NULL) OR (PrevUser IS NOT NULL AND [User] IS NULL)) THEN 1 END),
        ('Tag', CASE WHEN RN != 1 AND (PrevTag != Tag OR (PrevTag IS NULL AND Tag IS NOT NULL) OR (PrevTag IS NOT NULL AND Tag IS NULL)) THEN Tag END, CASE WHEN RN != 1 AND (PrevTag != Tag OR (PrevTag IS NULL AND Tag IS NOT NULL) OR (PrevTag IS NOT NULL AND Tag IS NULL)) THEN 1 END)
) AS C(Col, Val, Chk)
WHERE C.Chk = 1;

您可以取消打印结果,然后检查连续行中的更改,如下所示

select 
HistoryId,
column,
values
into #temp_up_values
from
(
 select * 
  from History 
   where DeptId='D34'
)src
unpivot
(
  values 
   for column 
   in ([User],[Tag],[Updateddate],[DeptId])
)up


select t2.* 
from 
#temp_up_values t1
join 
#temp_up_values t2
on t1.HistoryId=t2.HistoryId +1
and t1.column=t2.column and t1.values<>t2.values