使用CONCAT,COALESCE和ISNULL在SQL中无法连接NULL值

时间:2018-05-21 18:12:29

标签: sql-server sql-server-2017

我有一个带有多个连接的查询,我希望将两列中的记录合并为一个。如果一列是空的,那么我想显示一个列值作为结果。我尝试使用CONCATCOALEASEISNULL,但没有运气。我在这里缺少什么?

我的目标是,在查询中创建一个包含s.Script AS OriginalFromAnotherTable组合的列。以下查询运行但会抛出Invalid column name 'Original'Invalid column name 'FromAnotherTable'。当我尝试使用CONCATCOALEASEISNULL时。

SQL查询:

SELECT DISTINCT
       c.Name AS CallCenter,
       LTRIM(RTRIM(s.Name)) Name,
       d.DNIS,
       s.ScriptId,
      s.Script AS Original,
      (
          SELECT TOP 5 CCSL.Line+'; ' 
          FROM CallCenterScriptLine CCSL
          WHERE CCSL.ScriptId = s.ScriptId
          ORDER BY ScriptLineId FOR XML PATH('')
       ) AS FromAnotherTable,
         --CONCAT(s.Script, SELECT TOP 5 CCSL.Line+'; ' FROM dbo.CallCenterScriptLine ccsl WHERE ccsl.ScriptId = s.ScriptId ORDER BY ccsl.ScriptLineId xml path(''))
         --CONCAT(Original, FromAnotherTable) AS Option1,
         --COALESCE(Original, '') + FromAnotherTable AS Option2,
         --ISNULL(Original, '') + FromAnotherTable AS Option3,,
       r.UnitName AS Store,
       r.UnitNumber
FROM CallCenterScript s WITH (NOLOCK)
     INNER JOIN CallCenterDNIS d WITH (NOLOCK) ON d.ScriptId = s.ScriptId
     INNER JOIN CallCenter c WITH (NOLOCK) ON c.Id = s.CallCenterId
     INNER JOIN CallCenterDNISRestaurant ccd WITH (NOLOCK) ON ccd.CallCenterDNISId = d.CallCenterDNISId
     INNER JOIN dbo.Restaurant r WITH (NOLOCK) ON r.RestaurantID = ccd.CallCenterRestaurantId
WHERE c.Id = 5
      AND (1 = 1)
      AND (s.IsDeleted = 0 OR s.IsDeleted IS NULL)
ORDER BY DNIS ASC;

输出: enter image description here

这有效:

DECLARE @Column1 VARCHAR(50) = 'Foo',
        @Column2 VARCHAR(50) = NULL;

SELECT CONCAT(@Column1,@Column2);
SELECT COALESCE(@Column2, '') + @Column1
SELECT ISNULL(@Column2, '') + @Column1

所以我不确定我在原始查询中缺少什么。

3 个答案:

答案 0 :(得分:2)

查看您获得的结果中的第3行。在连接列(选项1,2,3)中,您将获得第一个脚本列两次。不是第一个+第二个像你期望的那样。

原因是因为您已将子查询别名"脚本"与查询中的另一列名称相同,这使其不明确。

更改子查询的别名,问题应该消失。我坦率地说你的查询没有引起错误。

编辑:您不能在同一级别的查询中使用另一列定义中的列别名。换句话说,你不能这样做:

SELECT 
  SomeColumn AS A
, (Subquery that returns a column) AS B
, A + B  --this is not allowed
FROM ...

您可以创建一个返回别名列的CTE,然后在从CTE中选择的主查询中连接它们,或者您必须使用别名的原始来源,如下所示:

SELECT 
  SomeColumn AS A
, (Subquery that returns a column) AS B
, SomeColumn  + (Subquery that returns a column)  --this is fine
FROM ...

答案 1 :(得分:0)

我采用了另一种方法,而不是创建单独的列,我在ISNULL中使用了subQuery,它返回了我想要的结果。

<强>查询:

SELECT DISTINCT
       c.Name AS CallCenter,
       LTRIM(RTRIM(s.Name)) Name,
       d.DNIS,
       s.ScriptId,
      s.Script AS Original,
      (
          SELECT TOP 5 ISNULL(CCSL.Line, '')+'; ' + ISNULL(s.Script, '')
          FROM CallCenterScriptLine CCSL
          WHERE CCSL.ScriptId = s.ScriptId
          ORDER BY ScriptLineId FOR XML PATH('')
       ) AS FromAnotherTable,
       r.UnitName AS Store,
       r.UnitNumber
FROM CallCenterScript s WITH (NOLOCK)
     INNER JOIN CallCenterDNIS d WITH (NOLOCK) ON d.ScriptId = s.ScriptId
     INNER JOIN CallCenter c WITH (NOLOCK) ON c.Id = s.CallCenterId
     INNER JOIN CallCenterDNISRestaurant ccd WITH (NOLOCK) ON ccd.CallCenterDNISId = d.CallCenterDNISId
     INNER JOIN dbo.Restaurant r WITH (NOLOCK) ON r.RestaurantID = ccd.CallCenterRestaurantId
WHERE c.Id = 5
      AND (1 = 1)
      AND (s.IsDeleted = 0 OR s.IsDeleted IS NULL)
ORDER BY DNIS ASC;

答案 2 :(得分:0)

这是使用表变量的简化示例。

它不使用字段的子查询,而是使用CROSS APPLY。

CONCAT与STUFF结合用于将字符串粘合在一起。

declare @Foo table (fooID int identity(1,1) primary key, Script varchar(30));
declare @Bar table (barID int identity(1,1) primary key, fooID int, Line varchar(30));

insert into @Foo (Script) values 
('Test1'),('Test2'),(NULL);

insert into @Bar (fooID, Line) values 
(1,'X'),(1,'Y'),(2,NULL),(3,'X'),(3,'Y');

select  
 f.fooID, 
 f.Script,
 x.Lines,
 CONCAT(Script+'; ', STUFF(x.Lines,1,2,''))  as NewScript
from @Foo f
cross apply (
    select '; '+b.Line
    from @Bar b
    where b.fooID = f.fooID 
    FOR XML PATH('')
    ) x(Lines)

结果:

fooID Script  Lines   NewScript
----- ------- ------- -----------
1     Test1   ; X; Y  Test1; X; Y
2     Test2   NULL    Test2; 
3     NULL    ; X; Y  X; Y