Các Loại JOIN Trong SQL Server

Vũ Huy Tâm

JOIN là phép kết nối dữ liệu từ nhiều bảng lại với nhau. Khi bạn cần truy vấn các cột dữ liệu từ nhiều bảng khác nhau để trả về trong cùng một tập kết quả, bạn cần dùng JOIN. Đây có lẽ là chức năng được dùng nhiều nhất khi lập trình T-SQL. Nó giúp tái hiện lại thông tin thế giới thực từ dữ liệu lưu trữ trong mô hình quan hệ. Ví dụ, bạn cần JOIN bảng BanHang với bảng SanPham thông qua SanPhamID để lấy về thông tin đầy đủ của một đơn hàng bao gồm cả tên sản phẩm, vì người dùng cần quan tâm đến sản phẩm đó là gì thay vì mã hiệu của nó.
SQL Server cung cấp các kiểu JOIN là INNER JOIN, OUTER JOIN, và CROSS JOIN.

INNER JOIN trả về kết quả là các bản ghi mà trường được join ở hai bảng khớp nhau, các bản ghi chỉ xuất hiện ở một trong hai bảng sẽ bị loại.

(hình lấy từ codinghorror.com)

OUTER JOIN nới lỏng hơn, lấy về các bản ghi có mặt trong cả hai bảng và cả các bản ghi chỉ xuất hiện ở một trong hai bảng. Kiểu JOIN này được chia làm hai loại:

  • FULL OUTER JOIN: kết quả gồm tất cả các bản ghi của cả hai bảng. Với các bản ghi chỉ xuất hiện trong một bảng thì các cột dữ liệu từ bảng kia được điền giá trị NULL.
  • HALF OUTER JOIN (LEFT hoặc RIGHT): nếu bảng A LEFT OUTER JOIN với bảng B thì kết quả gồm các bản ghi có trong bảng A, với các bản ghi không có mặt trong bảng B thì các cột từ B được điền NULL. Các bản ghi chỉ có trong B mà không có trong A sẽ không được trả về.

CROSS JOIN: mỗi bản ghi của bảng A được kết hợp với tất cả các bản ghi của bảng B, tạo thành một tích Đề-các giữa hai bảng (số bản ghi trả về bằng tích của số bản ghi trong hai bảng).

Ví dụ:

CREATE TABLE T1(ID1 INT, Ten VARCHAR(100) )
INSERT INTO T1
SELECT 1, 'Mozart' UNION ALL
SELECT 2, 'Beethoven' UNION ALL
SELECT 3, 'Chopin' 
 
CREATE TABLE T2(ID2 INT, Email VARCHAR(100) )
INSERT INTO T2
SELECT 2, 'beethoven@gmail.com' UNION ALL
SELECT 3, 'chopin@hotmail.com'  UNION ALL
SELECT 4, 'haydn@yahoo.com'  UNION ALL
SELECT 5, 'bach@yahoo.com'

INNER JOIN:

FULL OUTER JOIN:

LEFT OUTER JOIN:

CROSS JOIN:

Lưu ý là “A INNER JOIN B” có thể viết tắt thành “A JOIN B”, còn “A LEFT OUTER JOIN B” có thể viết “A LEFT JOIN B”.

Trong các loại JOIN trên, chỉ trừ HALF OUTER JOIN còn tất cả đều có tính đối xứng, nghĩa là “A JOIN B” tương tự như “B JOIN A”. Riêng HALF OUTER JOIN thì phân biệt thứ tự, ví dụ “A LEFT JOIN B” khác với “B LEFT JOIN A”. Tuy nhiên, “A LEFT JOIN B” tương đương với “B RIGHT JOIN A”, vì thế để tránh nhầm lẫn tôi luôn hay dùng LEFT JOIN thay cho RIGHT JOIN, và ngầm qui định trong đầu là A là bảng chính còn B là bảng join (bảng để kéo thêm dữ liệu vào).

Bạn cần đặc biệt chú ý khi dùng CROSS JOIN vì nó có thể tạo ra bùng nổ về số bản ghi. Ví dụ nếu hai bảng có số bản ghi tương ứng là 1 nghìn và 1 triệu thì kết quả sẽ là 1 tỷ bản ghi. Nói chung CROSS JOIN thường được dùng rất ít nhưng vẫn có lúc cần, ví dụ bảng kết quả điểm thi của sinh viên là CROSS JOIN của bảng sinh viên và bảng môn học (giả sử mỗi sinh viên cần lấy đủ tất cả các môn học).

Các kiểu viết JOIN

Cách viết JOIN như trên gọi là theo kiểu ANSI (ANSI style), cách viết kiểu cũ là đưa điều kiện join vào mệnh đề WHERE:

--INNER JOIN kiểu ANSI
SELECT *
FROM T1 JOIN T2 ON T1.ID = T2.ID
--INNER JOIN kiểu cũ
SELECT *
FROM T1, T2
WHERE T1.ID = T2.ID
 
-- LEFT OUTER JOIN kiểu ANSI
SELECT *
FROM T1 LEFT JOIN T2 ON T1.ID = T2.ID
--LEFT OUTER JOIN kiểu cũ
SELECT *
FROM T1, T2
WHERE T1.ID *= T2.ID

Cả hai kiểu viết đều cho cùng kết quả và cũng không khác nhau về hiệu năng thực hiện. Tuy vây bạn có thể thấy cách viết kiểu ANSI trong sáng hơn. Kiểu viết này gần với diễn đạt của ngôn ngữ tự nhiên hơn, nó tách bạch rõ ràng điều kiện join ra khỏi điều kiện lọc dữ liệu (dùng ở mệnh đề WHERE). Đây là kiểu viết bạn nên dùng. Microsoft trong 10 năm qua liên tục khuyến cáo dùng kiểu viết ANSI và nhắc nhở, các phiên bản sau có thể sẽ không hỗ trợ kiểu cũ. Và đến nay, bản SQL Server 2008 đã không còn hỗ trợ LEFT JOIN viết theo kiểu cũ (trừ khi bạn phải đặt lại COMPATIBILITY_LEVEL xuống mức thấp hơn).




Tags: , , , , , , ,

75 Comments
Posted on 27/10/2010 | Categories: SQL Server Programming

Các bài viết tương tự

Comments
  • Tai Thien (27/01/2011 10:29 pm)

    Hi anh,

    Đây là blog mà em rất thích và thấy học được rất nhiều điều từ đây. Rất cảm ơn blog này của anh và mong blog ngày càng mạnh hơn có nhiều kiến thức khác bổ ích hơn.

    Em cũng đang tập trung muốn tìm hiểu về SQL Server, thì hiện em có 2 phân vân:

    1. Trong JOIN có nên lồng SELECT vào không:

    vd: INNER JOIN (SELECT EmpID FROM Employee WHERE EmpID = @empID) B

    ON A.xxx = B.xxx

    2. Hoặc là sẽ thực hiện 2 SELECT A và B riêng với WITH, sau đó JOIN 2 bảng A và B lại.

    Thì mục đích SELECT trước khi JOIN là để lọc bớt số records và chỉ JOIN các records cần thiết. Thì anh cho hỏi 2 cách trên cách nào tốt hơn, hoặc có cách nào tốt hơn 2 cách trên không?

    Chân thành cảm ơn anh và mong được học hỏi thêm.

  • Tai Thien (28/01/2011 12:49 am)

    Cho em hỏi thêm 1 ví dụ nữa: so sánh 2 cách truy vấn sau, cái nào hiệu quả tối ưu hơn

    1.

    WITH ProFilter AS (SELECT ProId, ProName FROM Products p WHERE p.DelFlag=0 AND Active=1 AND ShopID = 'taithien')

    SELECT p.*, pt.*

    FROM ProFilter p

    INNER JOIN ProductType pt

    WHERE p.ProTypeID = pt.ProTypeID

    2.

    SELECT *

    FROM Products p

    INNER JOIN ProductType pt

    WHERE p.ProTypeID = pt.ProTypeID AND p.DelFlag=0 AND Active=1 AND ShopID = 'taithien'

    2 cách viết trên trả về cùng kết quả, vì data rất lớn nên em cứ phân vân mãi không biết tốc độ của cách nào thực hiện nhanh hơn. Xin các anh cho ý kiến.

  • Vũ Huy Tâm (31/01/2011 5:44 am)

    Chào bạn,

    thay vì cứ phân vân mãi thì bạn chỉ việc chạy thử cả hai cách xem cách nào nhanh hơn thôi :) . Các cách bạn dùng không có gì khác nhau về mặt hiệu năng, vì khi hệ thống thực hiện tối ưu hóa thì các điều kiện tìm kiếm trên đều được qui về giống nhau, dù ở trong subquery hay trong mệnh đề join.

    Có 1 tình huống tôi có thể nghĩ được dùng subquery lợi hơn, là khi bảng B ở remote server được truy vấn qua linked server. Khi đó, dùng subquery trước để giảm bớt traffic qua mạng rồi mới join với kết quả của subquery.

  • NANIA (04/03/2011 12:12 am)

    Tôi không đồng ý với ý kiến của bạn Tâm.

    Theo như câu lệnh SQL của bạn Tai thien, mình thấy đoạn lệnh 1 là tối ưu hơn.

    WITH ProFilter AS (SELECT ProId, ProName FROM Products p WHERE p.DelFlag=0 AND Active=1 AND ShopID = ‘taithien’)

    SELECT p.*, pt.*

    FROM ProFilter p

    INNER JOIN ProductType pt

    WHERE p.ProTypeID = pt.ProTypeID

    Cụ thể là dữ liệu đã được lọc bớt dư thừa trong bảng product=> profilter để giảm không gian tìm kiếm cho câu lệnh join đằng sau.

    Còn trong đoạn lệnh thứ 2, bạn select toàn bộ dữ liệu ra và join trước khi loc, như vậy sẽ rất tốn thời gian của hệ thống, đồng thời nó phải làm việc với 1 lượng dữ liệu rất lớn.

  • NANIA (04/03/2011 12:15 am)

    Nếu các bạn đã được học môn CSDL ở trường, các bạn sẽ được học cách tối ưu câu lệnh truy vấn SQL. Trong đó cũng có đề cập tới các vấn đề này. Nó còn phức tạp hơn nhiều vì nó có sử dụng cả phép giao, hợp,…

  • Newbie (07/03/2011 5:44 am)

    Trang web này rất hay, cám ơn ban quản trị, tôi cũng đã học được rất nhiều từ trang web này :D

  • mercury11290 (17/06/2011 8:44 pm)

    Blog rất hữu ích.Mình đã tìm thấy nhiều điều còn thắc mắc ở đây.Thanks sqlviet.com

  • kojumi (04/07/2011 2:34 am)

    Chao ban NANIA,

    Ban dua tren co so nao ma lai chac chan rang query statement 1 lai toi uu hon?

    Ban co bao gio thu debug cac cau query chua?

    Neu ban nghien cuu ky hon ve thu tuc compile trong trinh compiler cua SQL thi ban se khong phat bieu nhu tren.

    Regards,
    Kojumi Tran

  • luu son (29/10/2011 10:17 pm)

    Bạn ơi! bạn có cái đề tài nào về SQL sever cho minh xin tham khảo với! Mình đàng làm về “Các thuật toán trong SQL sever dùng để thực thi câu lệnh Join”. Thanh bạn nhiều!

  • tri tai (11/02/2012 11:07 am)

    Mình không hiểu làm thế nào để join 3 bảng lại với nhau!!
    Vd: Cho lược đồ quan hệ:
    SinhVien(MaSV(khóa chính), HoTen,NgaySinh,Malop(khóa ngoại), GioiTinh,HocBong)
    Lớp(MaLop(khóa chinh), TenLop,SiSo,MaKhoa(khóa phụ)
    Môn Học(MaMH(khóa chính),TenMH,SoTiet)
    Kết Quả(MaSV,MaMH,DiemThi)
    a)Lập danh sách gồm: MaSV,HoTen,TenLop,TenKhoa
    b)Lập danh sách SV cho tất cả sinh có mã lớp là cdth12b, gồm: MaSV, HoTen,MaMH,DiemThi;
    bạn có thể giải thích cách làm cho mình hiểu ko? sẵn giả dùm mình bài ví dụ này không(làm tới đây bị bí rồi)?

    • Vũ Huy Tâm (22/02/2012 6:17 pm)

      Bạn PhuocHanTien phát hiện đúng là thiếu bảng Khoa. Nhưng cách viết của bạn rườm rà không cần thiết. JOIN nhiều bảng chỉ cần như vầy thôi:

      SELECT SV.MaSV, SV.HoTen, L.Tenlop, K.TenKhoa
      FROM SinhVien SV
      JOIN Lop L ON SV.Malop = L.Malop
      JOIN Khoa K ON L.MaKhoa = K.MaKhoa

      Cứ tiếp tục như thế bạn có thể JOIN vài chục bảng cũng được.

      • PhuocHanTien (23/02/2012 10:15 am)

        Vũ Huy Tâm có biết nếu bạn viết như thế sẽ xảy ra thiếu dữ liệu trong 1 số trường hợp k! Mình Vd nhé:
        1 sinh viên thuộc 1 khoa nhưng chưa sắp xếp vào lớp nào khi đó sinh viên này sẽ k Select được ra đâu!

      • Vũ Huy Tâm (24/02/2012 3:00 pm)

        Như trường hợp bạn nêu thì chỉ cần thay JOIN bằng LEFT JOIN, nhưng cách viết join nhiều bảng chỉ cần như vậy. Cách viết của bạn kết quả không có gì khác nhưng rườm rà khó đọc hơn

      • Nguyễn Hưởng (28/10/2012 12:18 am)

        Cái này hay chưa từng thấy like like like

  • PhuocHanTien (22/02/2012 12:33 pm)

    Thiếu bảng Khoa bạn ơi! Mình VD bảng khoa như thế này nhé
    KHOA(MaKhoa, TenKhoa)
    a.

    SELECT Tmp1.MaSv, Tmp1.HoTen, Tmp1.TenLop, K.TenKhoa
         (SELECT Sv.MaSv, Sv.HoTen, L.TenLop, L.MaKhoa
               FROM SinhVien AS Sv LEFT OUTER JOIN Lớp AS L ON(Sv.MaLop = L.MaLop)) AS Tmp1
          LEFT OUTER JOIN KHOA AS K ON(Tmp1.MaKhoa = K.MaKhoa)

    Đầu tiên bạn lấy tất cả sinh viên rồi nối với lớp để tạo ra bảng Tmp1 rồi lại lấy bảng Tmp1 nối với bảng KHOA
    Câu lệnh INNER JOIN là liên kết 2 bảng và lấy ra những dòng giống nhau ở 2 bảng(chỉ những dòng giống nhau mới lấy) còn LEFT OUTER JOIN liên kết 2 bảng nhưng lấy ưu tiên bảng bên trái có nghĩa là lấy tất cả các dòng của bảng trái.
    CÁCH KHÁC NÈ:

    ;
    WITH bc AS
    (
    SELECT Sv.MaSv, Sv.HoTen, L.TenLop, L.MaKhoa
               FROM SinhVien AS Sv LEFT OUTER JOIN Lớp AS L ON(Sv.MaLop = L.MaLop)
    )
     
    SELECT bc.MaSv, bc.HoTen, bc.TenLop, bc.TenKhoa
               FROM bc  LEFT OUTER JOIN KHOA AS K ON(bc.MaKhoa = K.MaKhoa)

    nối cũng giống như trên thôi chỉ khác là dùng câu lệnh khác mà thôi
    b.

    SELECT Sv.MaSv, Sv.HoTen, KQ.MaMH, KQ.DiemThi
              FROM SinhVien AS Sv LEFT OUTER JOIN Kết Quả AS KQ ON(Sv.MaSv = KQ.MaSv)
              WHERE Sv.MaLop = 'cdth12b'
    • PhuocHanTien (22/02/2012 12:35 pm)

      Ah câu a mình viết thiếu

      SELECT Tmp1.MaSv, Tmp1.HoTen, Tmp1.TenLop, K.TenKhoa
               FROM (SELECT Sv.MaSv, Sv.HoTen, L.TenLop, L.MaKhoa
                            FROM SinhVien AS Sv LEFT OUTER JOIN Lớp AS L ON(Sv.MaLop = L.MaLop)) AS Tmp1
               LEFT OUTER JOIN KHOA AS K ON(Tmp1.MaKhoa = K.MaKhoa)
      • Tien Duong Van (23/03/2016 11:00 pm)

        Mình đồng ý vs suy nghĩ của bạn, nhưng cũng thử giả sử lớp chưa dc xếp vào khoa thì sao? Cũng giống như sinh viên chưa dc xếp vào lớp ấy.

  • Minh Đức (25/02/2012 4:08 am)

    tài liệu hay và cụ thể

  • Che Linh (08/03/2012 1:09 am)

    Blog mình cảm thấy rất hay, giờ thấy hiểu rõ hơn cấu trúc của các mệnh đề và các trường hợp sử dụng của nó

  • Duong Tran (06/04/2012 1:24 am)

    Mình muốn hỏi thêm một trường hợp. Những ví dụ ở đây mình cảm thấy đều là joint theo chiều ngang, thế còn joint theo chiều dọc thì sao. thức là có hai bảng hoàn toàn đồng nhất về các trường dữ liệu. Mình muốn truy xuất dữ liệu cùng lúc từ hai bảng thì phải làm thế nào??

    • Vũ Huy Tâm (06/04/2012 2:01 pm)

      Mình không thật hiểu lắm câu hỏi của bạn. Nếu bạn post lên ví dụ cụ thể thì để mình xem có thể làm được không

  • DA (13/04/2012 4:35 am)

    Ý bạn Duong Trần ở đây giống kiểu như là 2 bảng giống hệt nhau nhưng dữ liệu khác nhau ,nên muốn “join theo chiều dọc” :d. Cái này không có nhé bạn ,JOIN thực ra để kết hợp các bảng khác nhau nhưng có điểm chung là một Column nào đó để có thể kết hợp với nhau lấy dữ liệu cho dễ .

  • Giang (29/08/2012 11:13 am)

    Vũ Huy Tâm cho mình hỏi trong tập A giao B như vậy. Muốn lấy mỗi phần A mà ko giao vs B thôi thì làm ntn ?

    • Red Devilic (29/08/2012 9:55 pm)

      Giả sử A có 2 cột (X, Y)
      B có 2 cột (X, Z)

      Có thể sử dụng 3 cách

      - Sử dụng NOT EXISTS
      - Sử dụng EXCEPT
      - Sử dụng A LEFT JOIN B WHERE B.Z IS NULL ( Cần để ý dữ liệu B.Z có cho phép allow null hay không, vì nếu B được quyền NULL thì cách này không đúng nữa )

  • Hòa (10/09/2012 5:03 am)

    Giúp mình với Liên Kết 3 Bảng mà bị lỗi hoài.

    SELECT XK.*,NK.LoaiXe,NK.DongCo,NK.SoMay,NK.SNofProduct,NK.DangKiem,NK.ToKhaiHQ,DM.HoTenKH,DM.TenCTY,DM.MaSoThue,DM.DiaChi,DM.DienThoai,DM.SoFAX  FROM XuatKhoTV XK INNER JOIN NhapKhoTV NK ON XK.SoKhung=NK.SoKhung INNER JOIN DanhMucKhachHang DM ON XK.MaKH=DM.MaKH
    • Vũ Huy Tâm (11/09/2012 8:37 am)

      Xem qua query của bạn thì không thấy có gì sai. Bạn gặp lỗi gì?

  • Lien Ngo (14/09/2012 11:37 am)

    Cho mình hỏi muốn join 2 columm trong cùng 1 table làm ntn?

  • Lien Ngo (15/09/2012 10:14 pm)

    Vd: Có 2 column la TenNV, NguoiQuanLy trong table NV. Mình muốn hiển thị những người vừa làm nhân viên vừa làm quản lý.

    • NguyenNgoc (18/01/2013 12:39 am)

      Join là kết nối các bảng với nhau thông qua các ràng buộc dữ liệu ở các column tại các bảng đó, vừa cả cách thiết kế database như trên tớ thấy không ổn, cậu nên phân tích rõ hơn về mối quan hệ giữa các thực thể trên hệ thống mà cậu đang xét đến.

  • otcay09 (03/05/2013 9:09 pm)

    các bạn cho mình hỏi. mình đang có 3 bảng như sau:
    LOP(#malop,tenlop,hocky,namhoc,makhoi,magv)
    HOCSINH(#mahs,hoten,diachi,ngaysinh,gioitinh)
    PHANLOP(#malop,#mahs).
    hiện tại mình đang muốn nhóm những học sinh có cùng địa chỉ vào 1 lớp. dữ liệu sẽ được đưa vào bảng PHANLOP.
    bạn nào biết chỉ giúp mình với

  • Thinh (03/06/2013 7:39 am)

    Chào các bạn! Cho mình hỏi một chút nhé!
    Mình có 2 bảng có cấu trúc giống nhau: F1,F2,F3,F4
    Bảng 1 có giá trị như sau:
    A B 1 2
    A B 3 4
    A C 1 2

    Bảng 2 có giá trị như sau:
    A B 1 2
    A B 3 4
    A B 5 6
    A C 1 2

    Kết quả mình muốn như sau:
    A B 1 2 A B 1 2
    A B 3 4 A B 3 4
    A B 5 6
    A C 1 2 A C 1 2

    Rất mong các bạn giúp đỡ

    • Lucario (03/06/2013 9:22 am)

      Hi,

      Có lẽ bạn nên mô tả rõ hơn về việc lấy dữ liệu giữa 2 bảng này, vì hiện tại mình ko rõ ý định của bạn lắm.

      Tuy nhiên, trong ví dụ cụ thể bạn nêu, có thể dùng OUTER JOIN để lấy kết quả như trên.

  • Thinh (03/06/2013 9:27 pm)

    Cảm ơn bạn, OUTER JOIN mình đã dùng thử, khi ấy dòng thứ 3 sẽ là A B 5 6 A B 3 4 thay vì chỉ có A B 5 6 Null Null
    Mình mô tả lại như sau:
    Có 2 bảng với các trường CG BG ST DU
    Mình cần ghép 2 bảng lại theo cặp CG BG và sắp xếp theo ST (ST và DU ở 2 bảng có thể khác nhau)
    Trường hợp bảng 1 có cặp CG BG nhưng bảng 2 không có thì nó sẽ là CG BG Null Null và ngược lại (đúng ý mình muốn).
    Trường hợp bảng 1 và 2 có số lượng cặp CG BG bằng nhau thì nó sẽ là CG BG ST DU (đúng ý mình muốn).
    Nhưng khi gặp trường hợp 2 bảng đều có cặp CG BG nhưng khác nhau về số lượng (vì dụ bảng 1 có 2 cặp, bảng 2 có 3 cặp như ví dụ trên thì khi đó kết quả sẽ là:
    A B 1 2 A B 1 2
    A B 3 4 A B 3 4
    A B 5 6 A B 3 4
    Thực tế mình muốn là
    A B 1 2 A B 1 2
    A B 3 4 A B 3 4
    A B 5 6 A B Null Null

    Rất mong bạn giúp đỡ! (Mình dùng VB6 và CSDL là MDB)

    • Lucario (03/06/2013 10:57 pm)

      Nếu bạn muốn kết quả trả ra là:

      A B 1 2 A B 1 2
      A B 3 4 A B 3 4
      A B 5 6
      A C 1 2 A C 1 2

      thì phải join 2 bảng trên cả 4 trường. Còn nếu chỉ join 2 trường CG và BG thì số lượng bản ghi sẽ lớn hơn chứ ko phải chỉ có 4 bản ghi trên.

      Hoặc có thể mình ko hiểu rõ ý bạn lắm.
      Nếu được thì bạn gửi nick yahoo hoặc skype, trao đổi sẽ tiện hơn :)

  • Thinh (03/06/2013 11:06 pm)

    Cảm ơn bạn, bạn nói đúng, số bản ghi sẽ lớn hơn, mình sẽ lọc theo điều kiện ST và DU nữa.
    Vì 2 trường ST và DU khác nhau nên không thể dùng cả 4 trường để join, vì thế mình hơi bí và chưa có cách nào làm được, bạn giúp mình qua Skype nhé! thinh.duyen
    Cảm ơn bạn nhiều lắm!

  • Linh (05/11/2013 3:34 am)

    cho em hỏi muốn join biến bảng với 1 bảng thường thì phải làm như thế nào ạ ???

    • Vũ Huy Tâm (05/11/2013 10:04 am)

      Join như bình thường bạn ạ:

      SELECT * FROM dbo.BangThuong T JOIN @BienBang B ON T.Col = B.Col
      • Linh (06/11/2013 9:50 am)

        đây là biến bảng của em
        http://i772.photobucket.com/albums/yy6/windlinh94/Untitled_zps11343144.png
        nhưng khi join biến bảng vs bảng thường thì nó hiện lỗi như sau
        Msg 1087, Level 15, State 2, Line 2
        Must declare the table variable “@diemtrungbinh”.

        • Vũ Huy Tâm (06/11/2013 10:13 am)

          Bạn cần đặt alias cho biến bảng:

          SELECT ...
          FROM @diemtrungbinh DTB JOIN sinh_vien SV ON SV.Malop = DTB.Malop
          • Linh (06/11/2013 10:45 am)

            thank :D làm đc rồi ạ

  • Tuệ (04/12/2013 5:31 am)

    cho em hỏi chút ạ, em có 2 bảng như thế này thì sẽ phải dùng câu lệnh inner join như thế nào ạ?
    kho(MaKho,TenKho)
    phieuchuyenkho(MaPhieuChuyenKho,NgayChuyenKho,MaKhoDi,MaKhoDen)

  • canh (09/12/2013 11:58 pm)

    cho mình hỏi muốn lấy 3 cột khác nhau từ 3 bảng khác nhau thì phải dùng câu lệnh inner join như thế nào..cảm ơn mọi người nhiều.!!

  • Trung (21/05/2014 1:10 am)

    Cho mình hỏi: mình có 1 csdl khá lớn, khoảng 500 ngàn records. Mình sử dụng inner join để join 4 bảng kèm điều kiện where nhưng khi chạy query thì bị time out. Vậy có cách viết nào tối ưu hoá thời gian xử lý mà ko phải chỉnh thông số time out ko mọi người?

    • tung (25/05/2014 11:44 pm)

      Bạn cần thêm index cho các trường khóa ngoại của các bảng join xem sao nhé ! Có thể xem thêm plan của nó để biết câu lệnh đã có index chưa.

  • Hậu (24/05/2014 1:02 am)

    Chào các bạn. Mình dùng Visual Foxpro. Mình có 2 table. Table BN có 2 trường: Hoten chứa tên bệnh nhân, MaBV chứa mã bệnh viện bệnh nhân khám (nhiều bệnh nhân có thể khám 1 bệnh viện và 1 bệnh nhân có thể khám nhiều bệnh viện tức là các record có thể trùng nhau). Table BV có trường MaBV, TenBV (MaBV và TenBV là duy nhất). Trong BN.MaBV có thể có giá trị không nằm trong BV.MaBV và ngược lại (ví dụ: BN.MaBV là a, b, b, a, c, d, c còn BV.MaBV là c, d, e, f). Mình cần lọc dữ liệu theo 2 trường hợp sau:
    1. Các trường của table BN và BV.TenBV với điều kiện BN.MaBV có giá trị trong BV.MaBV (các bản ghi của BN có MaBV là c, d trong ví dụ).
    2. Các trường của table BN với điều kiện BN.MaBV không nằm trong BV.MaBV (các bản ghi của BN có MaBV là a, b trong ví dụ).
    Các bạn giúp mình lọc dữ liệu với, mình cảm ơn.

  • Hậu (24/05/2014 1:23 am)

    Câu 1 mình làm được rồi bằng inner join, các bạn giúp mình câu 2 nhé.

  • Mai (26/05/2014 5:18 am)

    Cảm ơn! Bài viết rất hay.

  • lê văn kiên (28/05/2014 10:10 pm)

    Mình muốn hỏi các bạn mình có thể sử dụng câu lệnh select như thế nào để thay thế câu lệnh join giữa nhiều bảng

    • Red Devilic (02/06/2014 3:25 am)

      SELECT ….. FROM TABLE_A a, TABLE_B b WHERE a.ID = b.ID

  • Đỗ Anh Đức (25/06/2014 9:45 pm)

    Bài viết trên vẫn chưa diễn tả hết ý nghĩa của các loại JOIN, dẫn đến người đọc có thể hiểu chưa hết gây nhầm lẫn. Mình cũng không đồng tình với cách bạn diễn giải về các hình ảnh, hoàn toàn gây nhầm lẫn! Hoặc do cách diễn đạt không rõ nghĩa!
    Ví dụ bạn đưa ra quá đặc biệt, không thể hiện được rõ ràng sự khác nhau:

    Đây nhé, các bạn thử thêm dòng sau:
    INSERT INTO T2
    SELECT 2, ‘truebrothers@gmail.com’

    Sau đó chạy lại các câu lệnh JOIN ở trên, xem kết quả có giống các bạn dự đoán (nếu theo như mô tả ở trên).

    • Red Devilic (26/06/2014 2:06 am)

      Hình ảnh trong bài có gì nhầm lẫn vậy bạn ? Hình ảnh thể hiện các phép JOIN trên là kinh điển và rất phổ biến, tài liệu nào cũng có.
      Ví dụ cũng không có gì khó hiểu, có thể do cách bạn đọc và hiểu khác với đa số những người còn lại.

      Mình thêm dòng dữ liệu trên và kết quả không cần chạy cũng sẽ ra như mình dự đoán.

      Bạn có thể chía sẻ cách bạn dự đoán kết quả và câu JOIN trả về kết quả khác nhau như thế nào không ?

      Thanks.

      • Đỗ Anh Đức (05/09/2014 4:42 am)

        Ví dụ bạn đưa ra hơi đặc biệt, quan hệ dữ liệu 2 bảng T1 và T2 là quan hệ 1-1, không thể hiện được sự có thể tăng lên về số lượng record trả về.
        Đọc bài viết của bạn, theo dõi cả ví dụ ,mình nghĩ như sau: Tổng số record của T1 là 3, Tổng số record của T2 là 4
        – T1 INNER JOIN T2, số record trả về là 2 -> nghĩ rằng đây là số record trùng nhau của 2 bảng
        – T1 LEFT JOIN T2, số record trả về là 3, sau đó xem lại hình vẽ -> nghĩ rằng LEFT JOIN thì max record trả về cùng lắm là bằng tổng số record của T1.
        – T1 FULL OUTER JOIN T2, tổng số record trả về là 5.

        KẾT LUẬN: Bạn nên lấy ví dụ 2 bảng T1 và T2 có quan hệ n-n.
        - Hình minh họa là kinh điển nhưng mình thấy ko thỏa mãn, vì không thể hiện được sự tăng lên về dữ liệu trả về!

        • Vũ Huy Tâm (05/09/2014 9:01 am)

          Theo cách mình hiểu hình vẽ trên chỉ diễn tả logic của phép join, bản ghi nào được kéo vào, bản ghi nào không, chứ không nói đến tổng số lượng bản ghi. Nếu T1 và T2 là quan hệ 1-n, các bản ghi của T1 sẽ được lặp lại cho mỗi bản ghi từ T2. Tuy nhiên điều này thật khó thể hiện trong một hình vẽ đơn giản.
          Mình cũng nhận thấy nếu đưa ví dụ T1 và T2 là 1-n thì phổ quát hơn (ý bạn nói là 1-n chứ n-n thì join làm gì nữa :) ?

  • Nhựt Khánh (21/08/2014 6:45 am)

    Chào Anh!!Cho em hỏi bây giờ em có các bảng như sau:
    LopHoc(MaLH(PK), TenLH, NgayKG)
    HocVien(MaHV(PK), MaLH(FK), HoTen, Ngáyinh, Email, Hinh)
    DiemThi(MaHV(PK), MaMH(PK), LanThi(PK), DiemThi, NgayThi)
    MonHoc(MaMH(PK), TenMH)

    Bây giờ em muốn join các bảng để trả về điểm thi từng môn theo lớp thì, các cột dữ liệu trả về sẽ là:
    [Tên Lớp Học], [Môn Học], [Điểm Cao Nhất], [Điểm Thấp Nhất], [Điểm Trung Bình]

    Vậy thì em phải làm như thế à????

  • Nong Huong (25/09/2014 7:49 am)

    mình có 2 table HSCB va dmQUE_XA. lấy dữ liệu từ 2 talbe bằng cầu lệnh SQL sau:
    @”Select HSCB.SO_HO_SO as N’Sohoso’
    dmQUE_XA.NOI_DUNG as N’Quexa’,
    dmQUE_XA.NOI_DUNG as N’Diachixa’
    from HSCB left outer join
    left outer join dmQUE_XA on HSCB.QUE_XA=dmQUE_XA.MA
    left outer join dmQUE_XA ơn HSCB.QUE_XA=dmQUE_XA.MA”;
    để lấy dữ liệu lên DataTable rồi hiển thị thông tin lên 2 textbox là Quexa và Diachixa. nếu left outer join 2 lần sẽ bị lỗi. còn 1 lần thì chỉ lấy dữ liệu lên 1 textbox thôi
    Các bạn giúp mình giải quyết vấn đề này với

    • Vũ Huy Tâm (26/09/2014 9:50 am)

      Câu query của bạn không hoàn thiện “from HSCB left outer join…” <– theo sau left outer join phải lả một tên bảng.
      Nếu muốn join nhiều lần với cùng bảng thì bạn cần đưa alias vào kèm với tên bảng và điều kiện join phải khác nhau.

  • Chế Lụa (30/09/2014 11:51 pm)

    Chào Anh(chị) cho em hỏi chút a.
    Bây giờ em có bảng : Dangkykham(Id,IdBenhnhan,IdBacsi,Idnhanvien,Idlichkham,TinhTrangBenh,TrangThai) đã có cơ sở dữ liệu rồi ạ.
    và 1 bảng bệnh án: BenhAn(MaBA,IdDangKyKham,IdBenhnhan,IdBacsi,Idnhanvien,Idlichkham,TinhTrangBenh,Chandoan,KetLuanBenh,Tienthuoc,PhiDichVu,TongTien)
    chưa có thông tin cơ sở dữ liệu.
    Bây giờ em muốn lấy tất cả thông tin từ bảng đăng ký khám sang thông qua cái TrangThai để lưu vào bảng Bệnh án thì phải làm sao đây. Em mong các anh chị chỉ giúp với ạ.

    • BacVT (09/10/2014 4:33 am)

      Không biết đúng ý bạn không ?

      
      INSERT INTO BenhAn (tên các trường insert)
      SELECT (tên các trường select) FROM Dangkykham
      WHERE TrangThai='trạng thái'
      
  • Đoàn Văn Kỳ (06/11/2014 1:56 am)

    các bạn cho mình hỏi :
    -mình có 2 bảng tnhap ( dùng để ghi lại việc nhập) và txuat (ghi lại việc xuất)
    - mình join rất đơn giản dựa và [mã hàng] mà sao kết quả lại sai thế nhỉ
    Xem hình cụ thể : http://www.imageshack.us/i/knQ89MgSj

     
    SELECT * FROM tnhap 
    SELECT * FROM txuat  
    SELECT n.[Mã hàng], n.[Ngày nhập],  n.[số lượng] AS SL_N, x.[Ngày xuất],
    x.[số lượng] AS SL_X
     
    FROM tnhap n  JOIN txuat x           ON x.[mã hàng] = n.[mã hàng]
  • mychung (30/11/2014 10:44 am)

    cho mình hỏi có thể nối bốn bảng với nhau được không vậy?

    • NewNem (21/01/2015 12:51 am)

      mấy chục bảng cũng được miễn là bảng này có liên kết với bảng kia vd :D bảng A có khóa ngoại với B, B có khóa ngoại với C ,c có khóa ngoại với D …

  • Trung Nguyen (22/03/2015 5:49 am)

    Cho mình hỏi tí,
    Kết 2 tập dữ liệu từ 2 câu select thành 1 dùng từ khóa gì?! Nguyên tắc thế nào?! Tks all

  • Quang tu (10/04/2015 12:13 am)

    e có 1 cái VD: ae làm giùm hộ với. mình đã làm nhưng k thành công có gì giúp e cái
    VD: Hiển thị cột Tk_no (SOCAI),Ten_Tk (DMTK), và tổng tiền nhóm theo Tk_no trong quý II/2014 (từ ngày 01/04/2014 đến 30/06/2014) có tổng tiền theo nhóm lớn hơn 100.000.000 và sắp xếp tăng dần theo Tk_no (chú ý dùng Having trong SQL)

  • Lượng Trọng Nguyễn (10/05/2015 2:29 am)

    Em có 1 câu hỏi như sau :” em có 3 bảng : tinh_thanh(id_tt,ten_tt), quan_huyen(id_qh,ten_qh,id_tt) và nguoidung(id_ngdung,ten_ngdung,id_qh)
    giờ em muốn tìm kiếm những người có trong 1 tỉnh thành thì select viết thế nào ạ mong Mọi người giúp đỡ :(

  • vũ đình tuyển (19/08/2015 1:24 pm)

    Các bác chỉ giúp em cách thay đổi pass của người dùng trong data với, kế toán công ty em cứ thay người liên tuc mà em thì quên Pass cũ rồi

  • vũ đình tuyển (19/08/2015 1:26 pm)

    Các bác chỉ giúp em cách tìm pass cũ trong data với, thank nhiều ạ

  • Hiếu (14/01/2016 3:21 am)

    Hello mọi người,

    Mình đang bí cái JOIN hoặc GIAO, HỢP trong sql. anh em cho mình hỏi với.
    Mình có 1 table A chứa 1 số trường như trong image và table B nó là Cha của table A. Mình muốn Join kiểu gì mà có thể giử nguyên table A và thêm 1 số trường bên Table B qua nửa để mình so sánh giử data 2 bên. Anh em giúp với. Nếu được add skype giúp mình với. skype: hieunguyen.bkit

    http://postimg.org/image/tj1ghjyul/

    Thanks,

  • Minh Tâm (28/03/2016 10:15 am)

    Mình có cấu trúc kho như sau :
    Makho varhar(50)
    Tenkho Varchar(50)
    Solg int

    ví dụ dữ liệu
    Makho = “s11a01l1p1 ” – tên kho =’ Kho 11 dãy A lầu 1 vi trí 1″ – solg=0
    Makho = “s11a01l1p2 ” – tên kho =’ Kho 11 dãy A lầu 1 vi trí 2″ – solg=1
    Makho = “s11a01l1p3 ” – tên kho =’ Kho 11 dãy A lầu 1 vi trí 3″ — solg=0
    Makho = “s11a01l2p1 ” – tên kho =’ Kho 11 dãy A lầu 2 vi trí 1″ – - solg=1
    Makho = “s11a01l2p2 ” – tên kho =’ Kho 11 dãy A lầu 2 vi trí 2″ – solg=1
    Makho = “s11a01l2p3 ” – tên kho =’ Kho 11 dãy A lầu 2 vi trí 3″ — solg=0
    Makho = “s12a01l2p1 ” – tên kho =’ Kho 12 dãy A lầu 2 vi trí 1″ – - solg=1
    Makho = “s12a01l2p2 ” – tên kho =’ Kho 12 dãy A lầu 2 vi trí 2″ – solg=1
    Makho = “s12a01l2p3 ” – tên kho =’ Kho 12 dãy A lầu 2 vi trí 3″ — solg=0
    ….

    yêu cầu đặt ra như sau :
    Tính công suất 1 kho = số vị trí có hàng/tổng số vị trí có thể sử dụng

    các bạn iúp mình câu SQL với nha.
    Xin chân thành cám ơn.

    • TuânĐx (11/04/2016 8:36 am)
      SELECT SubStr(Makho,0,6) AS kho, SUM(solg)/COUNT(*) AS CongSuat FROM KhoTable GROUP BY SubStr(Makho,0,6)

      Bạn thử câu lệnh trên xem

      - Ở đây mình đặt tên bảng là KhoTable

      - Và mình hiểu ý bạn là tính công suất cho từng kho, ở đây có 2 kho là “s11a01″ và “s12a01″

  • Hello, I think your site might be having browser compatibility issues.
    When I look at your website in Firefox, it looks fine but
    when opening in Internet Explorer, it has some overlapping.
    I just wanted to give you a quick heads up! Other then that, superb blog!

Leave a Reply

Hướng dẫn: Để nhập mã T-SQL bạn dùng thẻ <pre lang="tsql"> và </pre>.
Ví dụ: <pre lang="tsql">SELECT * FROM MyTable</pre>