sql-server – 在哪里使用外部应用
主表 x------x--------------------x | Id | Name | x------x--------------------x | 1 | A | | 2 | B | | 3 | C | x------x--------------------x 详细信息表 x------x--------------------x-------x | Id | PERIOD | QTY | x------x--------------------x-------x | 1 | 2014-01-13 | 10 | | 1 | 2014-01-11 | 15 | | 1 | 2014-01-12 | 20 | | 2 | 2014-01-06 | 30 | | 2 | 2014-01-08 | 40 | x------x--------------------x-------x 当使用LEFT JOIN和OUTER APPLY时,我得到相同的结果. LEFT JOIN SELECT T1.ID,T1.NAME,T2.PERIOD,T2.QTY FROM MASTER T1 LEFT JOIN DETAILS T2 ON T1.ID=T2.ID 外部申请 SELECT T1.ID,TAB.PERIOD,TAB.QTY FROM MASTER T1 OUTER APPLY ( SELECT ID,PERIOD,QTY FROM DETAILS T2 WHERE T1.ID=T2.ID )TAB 我应该在哪里使用LEFT JOIN以及我应该在哪里使用OUTER APPLY 解决方法在以下情况下,应使用OUTER APPLY替换LEFT JOIN.1.如果我们想根据TOP n结果加入两个表 考虑我们是否需要从Master中选择Id和Name,并从Details表中为每个Id选择最后两个日期. SELECT M.ID,M.NAME,D.PERIOD,D.QTY FROM MASTER M LEFT JOIN ( SELECT TOP 2 ID,QTY FROM DETAILS D ORDER BY CAST(PERIOD AS DATE)DESC )D ON M.ID=D.ID 形成以下结果 x------x---------x--------------x-------x | Id | Name | PERIOD | QTY | x------x---------x--------------x-------x | 1 | A | 2014-01-13 | 10 | | 1 | A | 2014-01-12 | 20 | | 2 | B | NULL | NULL | | 3 | C | NULL | NULL | x------x---------x--------------x-------x 这将带来错误的结果,即,即使我们加入Id,它也只会从详细信息表中带来最新的两个日期数据而不管Id.所以正确的解决方案是使用OUTER APPLY. SELECT M.ID,D.QTY FROM MASTER M OUTER APPLY ( SELECT TOP 2 ID,QTY FROM DETAILS D WHERE M.ID=D.ID ORDER BY CAST(PERIOD AS DATE)DESC )D 这是工作:在LEFT JOIN中,只有在派生表D中执行查询后,才会将TOP 2日期加入MASTER.在OUTER APPLY中,它使用在OUTER APPLY中加入WHERE M.ID = D.ID,这样Master中的每个ID都将与TOP 2日期相结合,这将带来以下结果. x------x---------x--------------x-------x | Id | Name | PERIOD | QTY | x------x---------x--------------x-------x | 1 | A | 2014-01-13 | 10 | | 1 | A | 2014-01-12 | 20 | | 2 | B | 2014-01-08 | 40 | | 2 | B | 2014-01-06 | 30 | | 3 | C | NULL | NULL | x------x---------x--------------x-------x 2.当我们需要使用函数的LEFT JOIN功能时. 当我们需要从主表和函数中获取结果时,OUTER APPLY可以用作LEFT JOIN的替换. SELECT M.ID,C.PERIOD,C.QTY FROM MASTER M OUTER APPLY dbo.FnGetQty(M.ID) C 功能就在这里. CREATE FUNCTION FnGetQty ( @Id INT ) RETURNS TABLE AS RETURN ( SELECT ID,QTY FROM DETAILS WHERE ID=@Id ) 产生了以下结果 x------x---------x--------------x-------x | Id | Name | PERIOD | QTY | x------x---------x--------------x-------x | 1 | A | 2014-01-13 | 10 | | 1 | A | 2014-01-11 | 15 | | 1 | A | 2014-01-12 | 20 | | 2 | B | 2014-01-06 | 30 | | 2 | B | 2014-01-08 | 40 | | 3 | C | NULL | NULL | x------x---------x--------------x-------x 3.在取消隐藏时保留NULL值 考虑一下你有下表 x------x-------------x--------------x | Id | FROMDATE | TODATE | x------x-------------x--------------x | 1 | 2014-01-11 | 2014-01-13 | | 1 | 2014-02-23 | 2014-02-27 | | 2 | 2014-05-06 | 2014-05-30 | | 3 | NULL | NULL | x------x-------------x--------------x 当您使用UNPIVOT将FROMDATE和TODATE带到一列时,它将默认消除NULL值. SELECT ID,DATES FROM MYTABLE UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P 产生以下结果.请注意,我们错过了身份证号码3的记录 x------x-------------x | Id | DATES | x------x-------------x | 1 | 2014-01-11 | | 1 | 2014-01-13 | | 1 | 2014-02-23 | | 1 | 2014-02-27 | | 2 | 2014-05-06 | | 2 | 2014-05-30 | x------x-------------x 在这种情况下,可以使用APPLY(CROSS APPLY或OUTER APPLY,可以互换). SELECT DISTINCT ID,DATES FROM MYTABLE OUTER APPLY(VALUES (FROMDATE),(TODATE)) COLUMNNAMES(DATES) 形成以下结果并保留其值为3的Id x------x-------------x | Id | DATES | x------x-------------x | 1 | 2014-01-11 | | 1 | 2014-01-13 | | 1 | 2014-02-23 | | 1 | 2014-02-27 | | 2 | 2014-05-06 | | 2 | 2014-05-30 | | 3 | NULL | x------x-------------x (编辑:PHP编程网 - 黄冈站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |