• 使用For XML PATH 会影响Cross Apply 返回


    昨天在写语句的时候,遇到了一个现象,其实就是使用 Cross Apply做一个拼接字符串的而已。比如

    CREATE TABLE GoodsCatalog 
    (ID INT,
        Name NVARCHAR(50))    
    
    CREATE TABLE Goods
    (ID INT,
        GoodsCatalogID INT,
        Name NVARCHAR(50))  
    
    
    INSERT INTO GoodsCatalog
            ( ID, Name )
    VALUES  ( 1,'水果'),( 2,'体育用品')
    
    INSERT INTO Goods
            ( ID,GoodsCatalogID, Name )
    VALUES  (1,1,'苹果')
           ,(2, 1,'香蕉')
           ,(3, 2,'足球')
           ,(4, 2,'篮球')
    
    
    SELECT a.*,
            STUFF(B.GoodName,1,1,'') AS GoodName
        FROM GoodsCatalog a
            CROSS APPLY (SELECT '-' + b.Name
                                FROM Goods b
                                    WHERE b.GoodsCatalogID = a.ID FOR XML PATH('')) AS B(GoodName)
                                 
    /*
    ID    Name    GoodName
    1    水果    苹果-香蕉
    2    体育用品    足球-篮球
    */

    很平常是吧?但是如果在 GoodsCatalog  表里面添加多2条数据呢?就会变成这样了。明明说好的 Cross Apply会将不返回生成结果集的行喔!!为啥还会这样呢!?

    INSERT INTO GoodsCatalog
            ( ID, Name )
    VALUES  ( 3,'海鲜'),( 4,'衣服')
    
    SELECT a.*,
            STUFF(B.GoodName,1,1,'') AS GoodName
        FROM GoodsCatalog a
            CROSS APPLY (SELECT '-' + b.Name
                                FROM Goods b
                                    WHERE b.GoodsCatalogID = a.ID FOR XML PATH('')) AS B(GoodName)
    
    /* ID Name GoodName 1 水果 苹果-香蕉 2 体育用品 足球-篮球 3 海鲜 NULL 4 衣服 NULL */






    -------------------------------------------这是描述我是一个逗比的分割线--------------------------------------------------------------------------------------------------------------

    重新看了下联机文档里面的Apply 的用法

    使用 APPLY 运算符可以为实现查询操作的外部表表达式返回的每个行调用表值函数。表值函数作为右输入,外部表表达式作为左输入。通过对右输入求值来获得左输入每一行的计算结果,生成的行被组合起来作为最终输出。APPLY 运算符生成的列的列表是左输入中的列集,后跟右输入返回的列的列表。

    就是说,无论是 Cross Apply 还是 Outer Apply 后面都是跟随一个表值函数,会与左边的输入表每一行进行交叉。所以是否返回应该看 ()里面的语句本身。

    这里我又有疑问了,Goods 表里面没有 3,4 的结果啊,为什么还能显示。

    这个就是函数的问题了。假如写2个表值函数对比一下就很清晰了

    CREATE FUNCTION TestXML
    (@GoodsCatalogID INT)
    RETURNS @TABLE TABLE
    (
        GoodName varchar(200)
    )
    AS    
    begin
        ;WITH CTE(GoodName) AS
        (SELECT '-' + Name FROM Goods
            WHERE GoodsCatalogID = @GoodsCatalogID FOR XML PATH(''))
        INSERT INTO @TABLE (GoodName)
        SELECT GoodName 
            FROM CTE
        RETURN
    END
    
    CREATE FUNCTION TestTable
    (@GoodsCatalogID INT)
    RETURNS @TABLE TABLE
    (
        GoodName varchar(200)
    )
    AS    
    begin
        INSERT INTO @TABLE (GoodName)
        SELECT  Name FROM Goods
            WHERE GoodsCatalogID = @GoodsCatalogID
        RETURN
    END
    
    SELECT *
        FROM dbo.TestXML(3)
    
    /*
    GoodName
    NULL
    */
    
    
    SELECT * 
        FROM dbo.TestTable(3)
    
    /*
    GoodName
    */

    一个有返回,另外一个没有返回哦~~这个就知道为什么能交叉到值出来了吧。

    --------------------------------------------------------------------------------------这是证明我不认真的打脸分割线------------------------------------------------------------------------------------------------------------------------

    发现了这个问题,纯粹是因为对 Apply用法不清晰导致了……╮(╯_╰)╭~

    为大家献丑了

  • 相关阅读:
    【二】调通单机版的thrift-C++版本
    【一】调通单机版的thrift-python版本
    Spark在实际项目中分配更多资源
    Spark实际项目中调节并行度
    IDEA中大小写转换快捷键
    使用maven下载cdh版本的大数据jar包
    【Hive六】Hive调优小结
    【Hive五】Hive函数UDF
    【Hbase三】Java,python操作Hbase
    【Hive三】Hive理论
  • 原文地址:https://www.cnblogs.com/Gin-23333/p/4175418.html
Copyright © 2020-2023  润新知