排除CTE查询中的空行

时间:2014-10-14 12:54:44

标签: sql sql-server sql-server-2012

我是在SQL Server中使用CTE查询的新手。我在网上的帮助下构建了此查询,以便开始构建我的更改日志"突出显示我的数据库中所做的更改。请参阅下面链接的示例。我想排除没有变化的行。你能帮忙解决这个问题吗?

11月改变的第3行有空白值。我希望这一行不显示。我也不想做像WHERE row1<>这样的事情。 '' AND row2<> '' AND row3<> ''等,因为我的最终查询将包含更多行。这可能吗?

http://sqlfiddle.com/#!6/134bd/4/0

2 个答案:

答案 0 :(得分:2)

您可以使用以下选项。 下面使用COALESCE函数。

使用相同的数据,只是修改了sqlfiddle中的代码。 匹配时将CASE语句返回NULL并将数据类型转换为varchar,然后在其中使用COALESCE

下面修改过的脚本包含nTEXT列。您可以在DATALENGTH子句中将COALESCEWHERE一起使用。

<强>修改:

CREATE TABLE tblEmp
([memid] int, [empid] int, [name] varchar(50),[salary] int,  [room] varchar(50), changedate datetime, ntxt ntext);

INSERT INTO tblEmp
    ([memid], [empid], [name], [salary], [room], [changedate], [ntxt])
VALUES
(41, 1, 'peter', 1000, 'Regency', '11/4/2012', ''),
(43, 1, 'peterz', 2000, 'Regency','11/5/2013', 'nn') ,
(44, 1, 'peterz', 2000, 'Regency','11/7/2013', '') ,
(45, 4, 'sally', 2001, 'Sheratio','11/2/2013', '') ,
(46, 4, 'sally', 2000, 'Sheraton','11/6/2013', ''),
(47, 1, 'peter', 3000, 'Regency','12/4/2013', '') ,
(48, 4, 'sallye', 2000,'Sheraton 1', '11/9/2013', '') ,
(49, 4, 'sally', 3000, 'Sheraton','11/6/2013', 'kljslkdjflkajslkjasdlkjalskjdlakjsdlkjasldjfk')
;

 WITH cte  AS 
(
  SELECT   
          empid,
         name,
         salary, room,
          changedate,
          ntxt,
         rn=ROW_NUMBER()OVER(PARTITION BY empid ORDER BY changedate)
  FROM   tblemp
) 
SELECT *
FROM
(
    SELECT c1.empid, oldname=CASE WHEN c1.Name=c2.Name THEN NULL ELSE C1.Name END,
           newname=CASE WHEN c1.Name=c2.Name THEN NULL ELSE C2.Name END,
           oldsalary=CASE WHEN c1.salary=c2.salary THEN NULL ELSE C1.salary END,
           newsalary=CASE WHEN c1.salary=c2.salary THEN NULL ELSE C2.salary END, 
    oldroom=CASE WHEN c1.Room=c2.Room THEN NULL ELSE C1.Room END,
           newroom=CASE WHEN c1.room=c2.room THEN NULL ELSE C2.room END,
    c2.changedate
    , c2.ntxt
    FROM cte c1 INNER JOIN cte c2 
    ON c1.empid=c2.empid AND c2.RN=c1.RN+1 
) x
WHERE NOT (COALESCE(oldname, newname, CAST(oldsalary AS VARCHAR), CAST(newsalary AS VARCHAR), CAST(oldroom AS VARCHAR), CAST(newroom AS VARCHAR)) is null
    AND DATALENGTH(ntxt) = 0)
ORDER BY ChangeDate DESC

答案 1 :(得分:0)

与SQL Server 2012略有不同的方法是在公用表表达式中使用LAG以便能够逐行检测。 CTE基本上将每一行与前一行中的相关数据一起拉出,并在外部查询中进行直接比较以生成结果。

WITH cte AS (
  SELECT 
    empid, changeDate,
    LAG(name)   OVER (PARTITION BY empid ORDER BY changeDate) oldname,   name,
    LAG(salary) OVER (PARTITION BY empid ORDER BY changeDate) oldsalary, salary,
    LAG(room)   OVER (PARTITION BY empid ORDER BY changeDate) oldroom,   room
  FROM tblEmp
)
SELECT empid,
  CASE WHEN name<>oldname     THEN oldname   ELSE '' END oldname, 
  CASE WHEN name<>oldname     THEN name      ELSE '' END newname, 
  CASE WHEN salary<>oldsalary THEN oldsalary ELSE '' END oldsalary, 
  CASE WHEN salary<>oldsalary THEN salary    ELSE '' END newsalary, 
  CASE WHEN room<>oldroom     THEN oldroom   ELSE '' END oldroom, 
  CASE WHEN room<>oldroom     THEN room      ELSE '' END newroom,
  changeDate
FROM cte
WHERE oldname<>name OR oldsalary<>salary OR oldroom<>room
ORDER BY empid, changeDate;

An SQLfiddle to test with