道一纹字

种一棵树最好的时间是十年前,其次就是现在。

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

示例题目:
有如下一张表T0624A

T0624B

希望得到如下结果:

该如何写这个SQL?

示例数据:

CREATE TABLE T0624A
(
用户编号 VARCHAR(10),
用户地址 VARCHAR(20),
金额 INT
)

INSERT INTO T0624A VALUES
('001','花开村1号',10),
('002','花开村2号',15),
('003','花开村6号',15),
('004','花开村5号',16),
('005','花开村12号',8)

CREATE TABLE T0624B
(
微信用户订单号 VARCHAR(10),
用户编号 VARCHAR(50)
)

INSERT INTO T0624B VALUES
('90002','001,002,004'),
('90003','005')
View Code

查询sql:

WITH T AS (
SELECT 
    tb01.微信用户订单号
   ,tb02.VALUE
FROM( 
        SELECT 
            微信用户订单号
           ,[value] = CONVERT(xml,'<root><v>' + REPLACE(用户编号, ',', '</v><v>') + '</v></root>') 
        FROM T0624B ) AS tb01 
OUTER APPLY( 
                SELECT 
                    VALUE = N.v.value('.', 'varchar(100)') FROM tb01.[value].nodes('/root/v'
             ) N(v) ) AS tb02
)

SELECT A.*,T.微信用户订单号
FROM T0624A A
    LEFT JOIN T ON A.用户编号 = T.VALUE

 思路解析:

outer apply用法参考:https://www.cnblogs.com/ljhdo/p/4422622.html

outer apply 和cross apply的相同点是:

  • 先计算左表,后计算右表;
  • 对左表中的每一行记录,右表都要“逐行”计算,类似于相关子查询;

outer apply 和cross apply的不同点是:

  • outer apply:将左表作为保留表,如果右表没有匹配行,那么右表中的字段会设置为null,类似于left join。
  • cross apply:没有保留表,对于左表中的一行记录,如果右表中没有匹配行,那么该行记录不显示在最终结果集中,类似于inner join。

 其中子查询部分可以改成自定义函数,参考:https://www.cnblogs.com/wangfuyou/p/5854218.html

CREATE FUNCTION [dbo].[ufn_SplitStringToTable]
(
  @str VARCHAR(MAX) ,
  @split VARCHAR(10)
)
RETURNS TABLE
    AS 
RETURN
    ( SELECT    B.id
      FROM      ( SELECT    [value] = CONVERT(XML , '<v>' + REPLACE(@str , @split , '</v><v>')
                            + '</v>')
                ) A
      OUTER APPLY ( SELECT  id = N.v.value('.' , 'varchar(100)')
                    FROM    A.[value].nodes('/v') N ( v )
                  ) B
    )

 

posted on 2021-06-24 09:57  道一纹字  阅读(88)  评论(0)    收藏  举报