• CROSS APPLY & OUTER APPLY


    CROSS APPLY & OUTER APPLY

    CREATE TABLE [dbo].[Account](
    	[UserId] [int] IDENTITY(1,1) NOT NULL,
    	[Name] [nvarchar](50) NULL,
    	[Age] [int] NULL,
    	[Gender] [int] NULL,
    	[BirthDate] [datetime] NULL,
     CONSTRAINT [PK_Account] PRIMARY KEY CLUSTERED 
    (
    	[UserId] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    INSERT INTO [dbo].[Account]([UserId], [Name], [Age], [Gender], [BirthDate]) VALUES (1, N'User01', 21, 1, '2000-11-02 15:12:30.000');
    INSERT INTO [dbo].[Account]([UserId], [Name], [Age], [Gender], [BirthDate]) VALUES (2, N'User02', 19, 0, '2002-02-02 15:12:30.000');
    INSERT INTO [dbo].[Account]([UserId], [Name], [Age], [Gender], [BirthDate]) VALUES (3, N'User03', 20, 1, '2001-03-02 15:12:30.000');
    GO
    
    CREATE TABLE [dbo].[Message](
    	[Id] [int] IDENTITY(1,1) NOT NULL,
    	[UserId] [int] NULL,
    	[Message] [nvarchar](200) NULL,
    	[IsRead] [bit] NULL,
    	[CreateTime] [datetime] NULL,
     CONSTRAINT [PK_Message] PRIMARY KEY CLUSTERED 
    (
    	[Id] ASC
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    INSERT INTO [dbo].[Message]([Id], [UserId], [Message], [IsRead], [CreateTime]) VALUES (1, 1, N'Hello!', '0', '2021-11-28 15:16:14.000');
    INSERT INTO [dbo].[Message]([Id], [UserId], [Message], [IsRead], [CreateTime]) VALUES (2, 1, N'First Message', '0', '2021-11-28 15:17:07.000');
    INSERT INTO [dbo].[Message]([Id], [UserId], [Message], [IsRead], [CreateTime]) VALUES (3, 1, N'Second Message', '0', '2021-11-28 15:17:32.000');
    INSERT INTO [dbo].[Message]([Id], [UserId], [Message], [IsRead], [CreateTime]) VALUES (4, 3, N'Hello!', '0', '2021-11-27 15:17:51.000');
    GO
    

    INNER JOIN

    内连结,左右两表中交叉存在的交集记录.不会出现NULL

    SELECT msg.Id,ac.Name,msg.Message,msg.IsRead,msg.CreateTime FROM dbo.Message AS msg INNER JOIN dbo.Account AS ac ON ac.UserId =msg.UserId
    
    Id Name Message IsRead CreateTime
    1 User01 Hello! 0 2021-11-28 15:16
    2 User01 First Message 0 2021-11-28 15:17
    3 User01 Second Message 0 2021-11-28 15:17
    4 User03 Hello! 0 2021-11-27 15:17

    LEFT JOIN

    左侧为主表,进行匹配.如果右侧没有,则显示NULL

    SELECT msg.Id,ac.Name,msg.Message,msg.IsRead,msg.CreateTime FROM dbo.Message AS msg LEFT JOIN dbo.Account AS ac ON ac.UserId =msg.UserId
    
    Id Name Message IsRead CreateTime
    1 User01 Hello! 0 2021-11-28 15:16
    2 User01 First Message 0 2021-11-28 15:17
    3 User01 Second Message 0 2021-11-28 15:17
    4 User03 Hello! 0 2021-11-27 15:17

    OUTER JOIN

    RIGHT OUTER JOIN:
    右侧表为主表,进行匹配.如果左侧没有,则显示NULL.
    查询结果为右表的并集.

    LEFT OUTER JOIN:
    左侧表为主表,查询结果为左表的并集.

    SELECT msg.Id,ac.Name,msg.Message,msg.IsRead,msg.CreateTime FROM dbo.Message AS msg RIGHT OUTER JOIN dbo.Account AS ac ON ac.UserId =msg.UserId
    
    Id Name Message IsRead CreateTime
    1 User01 Hello! 0 2021-11-28 15:16
    2 User01 First Message 0 2021-11-28 15:17
    3 User01 Second Message 0 2021-11-28 15:17
    NULL User02 NULL NULL NULL
    4 User03 Hello! 0 2021-11-27 15:17

    CROSS APPLY

    如果不考虑外部表中的聚合函数.整体实现效果与INNER JOIN差不多.

    通过连结查询,优先进行left外部表计算,然后在保持left外部表所有数据行的基础上,对right表进行查询匹配.

    CROSS APPLY 可以根据当前左表的当前记录去查询右表;

    INNER JOIN 是根据左表的当前记录匹配右表整个结果集;

    执行查询/运算的顺序上,比INNER JOIN更严格.

    查询结果与INNER JOIN一致,为左右两表的交集.

    SELECT msg.Id,ac.Name,msg.Message,msg.IsRead,msg.CreateTime FROM dbo.Account AS ac CROSS APPLY (SELECT TOP (2) * FROM dbo.Message  WHERE ac.UserId=UserId ORDER BY CreateTime DESC) msg
    
    Id Name Message IsRead CreateTime
    3 User01 Second Message 0 2021-11-28 15:17
    2 User01 First Message 0 2021-11-28 15:17
    4 User03 Hello! 0 2021-11-27 15:17

    OUTER APPLY

    外联结,如果不考虑外部表中的聚合函数,与OUTER JOIN差不过.

    与OUTER JOIN的区别在于,OUTER APPLY的左右表执行/运算顺序.

    OUTER APPLY 可以根据当前左表的当前记录去查询右表;

    INNER JOIN 是根据左表的当前记录匹配右表整个结果集;

    查询结果与OUTER JOIN一致,为左/右表的并集.

    SELECT msg.Id,ac.Name,msg.Message,msg.IsRead,msg.CreateTime FROM dbo.Account AS ac OUTER APPLY (SELECT TOP (2) * FROM dbo.Message  WHERE ac.UserId=UserId ORDER BY CreateTime DESC) msg
    
    Id Name Message IsRead CreateTime
    3 User01 Second Message 0 2021-11-28 15:17
    2 User01 First Message 0 2021-11-28 15:17
    NULL User02 NULL NULL NULL
    4 User03 Hello! 0 2021-11-27 15:17

    OUTER APPLY

    运算测试1

    测试案例

    WITH m AS (
        SELECT
    	'数字' TypeGroup,
    	'1,2,3,4,5,6,7,8,9' info UNION ALL
    SELECT
    	'字母' TypeGroup,
    	'a,b,c,d,e,f,g,h,i' info
    )
    SELECT * FROM m;
    
    TypeGroup info
    数字 1,2,3,4,5,6,7,8,9
    字母 a,b,c,d,e,f,g,h,i
    WITH m AS (
        SELECT
    	'数字' TypeGroup,
    	'1,2,3,4,5,6,7,8,9' info UNION ALL
    SELECT
    	'字母' TypeGroup,
    	'a,b,c,d,e,f,g,h,i' info
    )
    -- SELECT * FROM m;
    SELECT A.TypeGroup,B.info
    FROM(  
        select TypeGroup, CONVERT(xml,'<root><v>' + REPLACE(info, ',', '</v><v>') + '</v></root>')  as info
        from m
    ) A
    OUTER APPLY(
        SELECT info = N.c.value('.', 'varchar(8000)')
        FROM A.info.nodes('/root/v') N(c)
    ) B
    
    TypeGroup info
    数字 1
    数字 2
    数字 3
    数字 4
    数字 5
    数字 6
    数字 7
    数字 8
    数字 9
    字母 a
    字母 b
    字母 c
    字母 d
    字母 e
    字母 f
    字母 g
    字母 h
    字母 i

    测试运算2

    WITH Z AS (
    SELECT '奇数' [Type],'1' [Value] UNION ALL
    SELECT '奇数' [Type],'3' [Value] UNION ALL
    SELECT '奇数' [Type],'5' [Value] UNION ALL
    SELECT '奇数' [Type],'7' [Value] UNION ALL
    SELECT '偶数' [Type],'2' [Value] UNION ALL
    SELECT '偶数' [Type],'4' [Value] UNION ALL
    SELECT '偶数' [Type],'6' [Value] UNION ALL
    SELECT '偶数' [Type],'8' [Value]
    )
    SELECT * FROM 
    (SELECT DISTINCT [Z].[Type] FROM Z) A 
    OUTER APPLY (
    SELECT [VALUES]=CAST((SELECT [Z].[Value] FROM Z WHERE Z.[Type]=A.[Type] FOR XML AUTO) AS NVARCHAR(MAX))
    ) B
    
    Type VALUES
    偶数
    奇数
  • 相关阅读:
    html5语法
    Addthis使用
    css font-weight原理
    css3 background
    jquery对标签属性操作
    给textarea添加背景图
    label的for属性
    css3 text-shadow
    z-index堆叠规则
    css3 @font-face
  • 原文地址:https://www.cnblogs.com/honk/p/15754077.html
Copyright © 2020-2023  润新知