Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Nơi sử dụng Áp dụng bên ngoài

LEFT JOIN nên được thay thế bằng OUTER APPLY trong các tình huống sau.

1. Nếu chúng ta muốn nối hai bảng dựa trên TOP n kết quả

Cân nhắc xem chúng ta có cần chọn Id không và Name từ Master và hai ngày cuối cùng cho mỗi Id từ Details bảng.

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

tạo thành kết quả sau

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

Điều này sẽ mang lại kết quả sai, tức là nó sẽ chỉ mang lại dữ liệu hai ngày mới nhất từ ​​Details bảng không phân biệt Id mặc dù chúng tôi tham gia với Id . Vì vậy, giải pháp thích hợp là sử dụng OUTER 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

Đây là cách hoạt động:Trong LEFT JOIN , TOP 2 ngày sẽ được kết hợp với MASTER chỉ sau khi thực hiện truy vấn bên trong bảng dẫn xuất D . Trong OUTER APPLY , nó sử dụng tham gia WHERE M.ID=D.ID bên trong OUTER APPLY , để mỗi ID trong Master sẽ được tham gia với TOP 2 ngày sẽ mang lại kết quả sau.

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. Khi chúng ta cần LEFT JOIN chức năng sử dụng các hàm functions .

OUTER APPLY có thể được sử dụng để thay thế bằng LEFT JOIN khi chúng ta cần lấy kết quả từ Master bảng và một hàm functions .

SELECT M.ID,M.NAME,C.PERIOD,C.QTY
FROM MASTER M
OUTER APPLY dbo.FnGetQty(M.ID) C

Và chức năng ở đây.

CREATE FUNCTION FnGetQty 
(   
    @Id INT 
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT ID,PERIOD,QTY 
    FROM DETAILS
    WHERE [email protected]
)

đã tạo ra kết quả sau

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. Giữ lại NULL giá trị khi hủy chia sẻ

Hãy xem xét bạn có bảng dưới đây

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

Khi bạn sử dụng UNPIVOT mang FROMDATETODATE thành một cột, nó sẽ loại bỏ NULL giá trị theo mặc định.

SELECT ID,DATES
FROM MYTABLE
UNPIVOT (DATES FOR COLS IN (FROMDATE,TODATE)) P

tạo ra kết quả dưới đây. Lưu ý rằng chúng tôi đã bỏ sót bản ghi của Id số 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

Trong những trường hợp như vậy, một APPLY có thể được sử dụng (CROSS APPLY hoặc OUTER APPLY , có thể hoán đổi cho nhau).

SELECT DISTINCT ID,DATES
FROM MYTABLE 
OUTER APPLY(VALUES (FROMDATE),(TODATE))
COLUMNNAMES(DATES)

tạo thành kết quả sau và giữ lại Id trong đó giá trị của nó là 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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server FOR JSON AUTO Ví dụ (T-SQL)

  2. Làm thế nào để tạo tên bảng theo ngày giờ?

  3. executive sp_executesql @sql và execute (@sql) SQL Server

  4. Coi cột là loại khác nhau để sắp xếp

  5. SQL Server Management Studio - Thêm / Di chuyển các Cột yêu cầu thả và tạo lại?