Sar*_*avu 10 sql-server left-join sql-server-2008 outer-apply
主表
x------x--------------------x
| Id | Name |
x------x--------------------x
| 1 | A |
| 2 | B |
| 3 | C |
x------x--------------------x
Run Code Online (Sandbox Code Playgroud)
详情表
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
Run Code Online (Sandbox Code Playgroud)
我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
Run Code Online (Sandbox Code Playgroud)
OUTER APPLY
SELECT T1.ID,T1.NAME,TAB.PERIOD,TAB.QTY
FROM MASTER T1
OUTER APPLY
(
SELECT ID,PERIOD,QTY
FROM DETAILS T2
WHERE T1.ID=T2.ID
)TAB
Run Code Online (Sandbox Code Playgroud)
我LEFT JOIN应该在哪里使用和我应该在哪里使用OUTER APPLY
Sar*_*avu 11
在下列情况下LEFT JOIN应更换A.OUTER APPLY
1.如果我们想根据TOP n结果加入两个表
考虑我们是否需要从表中选择每个日期Id和Name来自Master最后两个日期.IdDetails
SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
LEFT JOIN
(
SELECT TOP 2 ID, PERIOD,QTY
FROM DETAILS D
ORDER BY CAST(PERIOD AS DATE)DESC
)D
ON M.ID=D.ID
Run Code Online (Sandbox Code Playgroud)
形成以下结果
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
Run Code Online (Sandbox Code Playgroud)
这将带来错误的结果,即,即使我们加入,它也只会从Details表中带来最新的两个日期数据.所以正确的解决方案是使用.IdIdOUTER APPLY
SELECT M.ID,M.NAME,D.PERIOD,D.QTY
FROM MASTER M
OUTER APPLY
(
SELECT TOP 2 ID, PERIOD,QTY
FROM DETAILS D
WHERE M.ID=D.ID
ORDER BY CAST(PERIOD AS DATE)DESC
)D
Run Code Online (Sandbox Code Playgroud)
这是工作:在LEFT JOIN,TOP 2日期将加入到MASTER仅在派生表内执行查询之后D.在OUTER APPLY,它使用WHERE M.ID=D.ID内部连接OUTER APPLY,以便每个IDin Master将与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
Run Code Online (Sandbox Code Playgroud)
2.当我们需要LEFT JOIN使用功能时functions.
OUTER APPLYLEFT JOIN当我们需要从Master表和a 获得结果时,可以用作替代function.
SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
OUTER APPLY dbo.FnGetQty(M.ID) C
Run Code Online (Sandbox Code Playgroud)
功能就在这里.
CREATE FUNCTION FnGetQty
(
@Id INT
)
RETURNS TABLE
AS
RETURN
(
SELECT ID,PERIOD,QTY
FROM DETAILS
WHERE ID=@Id
)
Run Code Online (Sandbox Code Playgroud)
产生了以下结果
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
当您使用AND 将一个列UNPIVOT引入时,它将默认消除值.FROMDATETODATENULL
SELECT ID,DATES
FROM MYTABLE
UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P
Run Code Online (Sandbox Code Playgroud)
产生以下结果.请注意,我们已经错过了Id数字记录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
Run Code Online (Sandbox Code Playgroud)
在这种情况下的APPLY可用于(或者CROSS APPLY或OUTER APPLY,这是可互换的).
SELECT DISTINCT ID,DATES
FROM MYTABLE
OUTER APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)
Run Code Online (Sandbox Code Playgroud)
它形成以下结果并保留Id其价值所在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 |
| 3 | NULL |
x------x-------------x
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6338 次 |
| 最近记录: |