【问题标题】:Split function in T-SQLT-SQL 中的拆分函数
【发布时间】:2016-10-04 11:34:28
【问题描述】:

我有一个包含逗号分隔字符串的字段的表。我想创建返回以下结果的查询:

我想创建返回拆分文本的查询。例如:

表格中的数据:

| ID                                   | Names                            |
| ------------------------------------ | -------------------------------- |
| 63F5D993-3AC9-4EEA-8007-B669542BAD9A | John Smith,Kerry King,Tom Arraya |

要求的结果:

 ID                                   | Names                             
------------------------------------  | -----------
63F5D993-3AC9-4EEA-8007-B669542BAD9A  | John Smith                       
------------------------------------- | -----------
63F5D993-3AC9-4EEA-8007-B669542BAD9A  | Kerry King                       
------------------------------------- | -----------
63F5D993-3AC9-4EEA-8007-B669542BAD9A  | Tom Arraya  

我找到了 T-SQL 的“拆分”功能,但它的工作原理并不完全适合我的情况。我不能这样执行:

SELECT dbo.Split(dbo.name, ',') FROM dbo.Mytable

它只能执行如下:

SELECT * FROM dbo.Split('John Smith,Kerry King,Tom Arraya', ',')

但它不适合我。 我也尝试写光标:

DECLARE @bkb varchar(256)
DECLARE @Bkb_Cursor CURSOR 
SET @Bkb_Cursor = CURSOR SCROLL FOR  
SELECT bkb.best_know_by
  FROM  [sugarcrm_cmsru_dev].[dbo].[contacts] c
  left JOIN [dbo].[email_addr_bean_rel]  eb
  ON eb.[bean_id] = c.[id]
  JOIN [dbo].[email_addresses] ea
  ON ea.[id] = eb.[email_address_id]
  JOIN [dbo].[contacts_cstm] ccs
  ON eb.bean_id = ccs.id_c
  left JOIN [dbo].[BestKnowBy$] bkb
  ON c.[campaign_id] =bkb.Con_id
  where c.deleted = 0;  
OPEN @Bkb_Cursor;  
FETCH NEXT FROM @Bkb_Cursor
INTO @bkb;
WHILE @@FETCH_STATUS = 0
BEGIN  
      PRINT dbo.Splitfn(@bkb);
      FETCH NEXT FROM @Bkb_Cursor INTO @bkb;  
END
CLOSE @Bkb_Cursor;  
DEALLOCATE @Bkb_Cursor;  
GO

但它不起作用。我收到错误“此上下文中不允许列“dbo”,并且找不到用户定义的函数或聚合“dbo.Splitfn”。”

我该如何解决这个问题?

我的查询如下所示:

SELECT c.[id], 
       bkb.best_know_by
  FROM  [sugarcrm_cmsru_dev].[dbo].[contacts] c
  left JOIN [dbo].[email_addr_bean_rel]  eb
  ON eb.[bean_id] = c.[id]
  JOIN [dbo].[email_addresses] ea
  ON ea.[id] = eb.[email_address_id]
  JOIN [dbo].[contacts_cstm] ccs
  ON eb.bean_id = ccs.id_c
  left JOIN [dbo].[BestKnowBy$] bkb
  ON c.[campaign_id] =bkb.Con_id
  where c.deleted = 0; 

bkb.best_know_by 字段包含逗号分隔的字符串。在这种情况下如何使用“交叉申请”?

【问题讨论】:

  • 我认为您的查询中的联接是错误的,因为eaeb 之间的INNER JOIN 意味着ceb 之间的INNER JOIN。由于您使用了LEFT OUTER JOINbkb,因此您可能希望使用OUTER APPLY 而不是CROSS APPLYOUTER APPLY 的行为类似于 LEFT OUTER JOIN,这意味着即使函数本身没有返回行,也会返回行(函数返回的列将输出为 NULL)。 CROSS APPLY 表示 INNER JOIN,因此只有在函数中存在对应行时才会返回行。

标签: sql sql-server tsql split


【解决方案1】:

您需要将CROSS APPLY 与表格的结果集结合使用,该结果集将为每一行执行该函数:

SELECT st.ID, spl.value
FROM SplitTest st
CROSS APPLY string_split(st.Names, ',') spl

编辑: 关于将您的查询添加到您的问题,您可以执行以下操作:

;WITH CTE_Query AS (
    SELECT c.[id], 
       bkb.best_know_by
    FROM  [sugarcrm_cmsru_dev].[dbo].[contacts] c
    left JOIN [dbo].[email_addr_bean_rel]  eb
    ON eb.[bean_id] = c.[id]
    JOIN [dbo].[email_addresses] ea
    ON ea.[id] = eb.[email_address_id]
    JOIN [dbo].[contacts_cstm] ccs
    ON eb.bean_id = ccs.id_c
    left JOIN [dbo].[BestKnowBy$] bkb
    ON c.[campaign_id] =bkb.Con_id
    where c.deleted = 0
)
SELECT cte.id, spl.value
FROM CTE_Query AS cte
CROSS APPLY string_split(cte.best_know_by, ',') spl

【讨论】:

  • 我在我的问题中添加了详细信息。敬请期待。谢谢。
  • 在不拆分表结构的情况下,我建议您将整个内容包装在 CTE/子查询中,然后执行 CROSS APPLY。见编辑。
【解决方案2】:

交叉申请就可以了

Select A.ID
      ,Names = B.Item   -- << Return Field from your Split Function
 From  YourTable A
 Cross Apply (Select * from dbo.Split(A.Names, ',') ) B

您的查询

SELECT c.[id]
      ,S.*      --<< Removed bkb.best_know_by and Replaced with S.* (don't know your Split() Return Field)
 FROM  [sugarcrm_cmsru_dev].[dbo].[contacts] c
 LEFT JOIN [dbo].[email_addr_bean_rel]  eb ON eb.[bean_id] = c.[id]
 JOIN [dbo].[email_addresses] ea ON ea.[id] = eb.[email_address_id]
 JOIN [dbo].[contacts_cstm] ccs   ON eb.bean_id = ccs.id_c
 LEFT JOIN [dbo].[BestKnowBy$] bkb   ON c.[campaign_id] =bkb.Con_id
 Cross Apply dbo.Split(bkb.best_know_by,',')  S
 where c.deleted = 0;

【讨论】:

  • 您不需要将拆分函数包装在子查询中 - Cross Apply dbo.Split(A.Names, ',') B 将产生与 Cross Apply (Select * from dbo.Split(A.Names, ',') ) B 相同的输出
  • @knuckles 是的,你是对的。把这归结为强迫症和旧习惯。没有性能影响,如果您只想选择第 1 项和第 3 项(例如),则必须将其包装
  • 我在我的问题中添加了详细信息。敬请期待。谢谢。
  • @Seva 更新答案见第二部分
  • 另一个观察结果(老实说,我不是来找你的)-CROSS APPLY 声明实际上暗示了INNER JOIN。要保留上述连接的 LEFT OUTER JOIN 行为,您将改用 OUTER APPLY。 TBH,我认为原始问题中的连接已经混淆了,所以我不确定 OP 想要什么。
猜你喜欢
  • 2010-10-16
  • 2014-02-05
  • 1970-01-01
  • 1970-01-01
  • 2019-01-21
  • 2017-05-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多