【问题标题】:Unable concate NULL value in SQL using CONCAT, COALESCE and ISNULL无法使用 CONCAT、COALESCE 和 ISNULL 在 SQL 中连接 NULL 值
【发布时间】:2018-05-21 18:12:28
【问题描述】:

我有一个包含多个连接的查询,我想将两列中的记录合并为一列。如果一列是空的,那么我想显示一列值作为结果。我尝试使用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;

输出:

这行得通:

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

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

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

【问题讨论】:

  • 我不确定你想达到什么目的,但我查看了代码并且我有一个问题:我看到你正在计算列脚本与 XML 子句,以及你下面的 SELECT 中的两行指的是专栏脚本。你在做吗?
  • 小心使用那个 nolock 提示。它比大多数人意识到的要险恶得多。 blogs.sentryone.com/aaronbertrand/bad-habits-nolock-everywhere
  • @BartoszSiemasz 所以基本上,我只从一张桌子上阅读,现在我从两张桌子上阅读。使用 XML 的唯一原因是将多行合二为一。这能回答你的问题吗?
  • 你为什么要连接s.Script +'; ', Script?你觉得s.ScriptScript有什么区别?你的别名子查询?尝试给它一个不同的名称以避免歧义。

标签: sql-server sql-server-2017


【解决方案1】:

查看您获得的结果中的第 3 行。在您的连接列(Option1、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 ...

【讨论】:

  • 有道理。如果我将s.Script AS Original 命名为FromAnotherTable 或任何其他名称,则我不能使用CONCAT。它在我的别名上给了我无效的列名错误。
【解决方案2】:

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

查询:

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;

【讨论】:

    【解决方案3】:

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

    它使用 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-12
      • 2015-06-25
      • 2015-02-13
      • 1970-01-01
      相关资源
      最近更新 更多