PDA

View Full Version : Kết quả sai lệch khi truy vấn nhiều bảng giúp mình với



coolboy_9x
17-08-2010, 16:46
Đây là diagram của mình :

http://i552.photobucket.com/albums/jj358/truongvancuong_bg/diagram.jpg

Đây là dữ liệu của các bảng :

http://i552.photobucket.com/albums/jj358/truongvancuong_bg/dulieu.jpg


Câu hỏi yêu cầu tạo view dondh_mavtu_tongslnhap bao gồm các thông tin sau : sodh,ngaydh,mavtu,sldat,tổng số lượng đã nhập hàng

Câu lệnh của mình tạo view này là :

Create view dondh_mavtu_tongslnhap
as
select DonDH.SoDH,DonDH.NgayDH, VATTU.MaVTu,VATTU.TenVTu, CTDONDH.SLDat, Sum(CTPNHAP.SLNhap)
from CTDONDH,DONDH,VATTU,CTPNHAP
where CTPNHAP.MaVTu=VATTU.MAVTu and VATTU.MAVTu=CTDONDH.MAVTu and CTDONDH.SoDH=DONDH.SoDH
group by DONDH.SoDH,DonDH.NgayDH, VATTU.MaVTu,VATTU.TenVTu,CTDONDH.SLDat

Mình k hiểu tại sao kết quả lại thành :

http://i552.photobucket.com/albums/jj358/truongvancuong_bg/sai-1.jpg


Các bạn có nhìn KQ với các bảng dữ liệu bên trên sẽ thấy sai lệch


Trường hợp với câu hỏi này cũng vậy :

Tạo view tonghop_nhap_xuat gồm các thông tin sau :
sodh,sopn,mavtu,slnhap,slxuat

Đây là câu lệnh của mình :
Create view tonghop_nhap_xuat
as
select pnhap.sodh,pnhap.sopn,ctpnhap.mavtu,slnhap,sldat
from pnhap,ctpnhap,ctdondh
where pnhap.sopn=ctpnhap.sopn and pnhap.sodh=ctdondh.sodh and ctdondh.mavtu=ctpnhap.mavtu

Kết quả


http://i552.photobucket.com/albums/jj358/truongvancuong_bg/sai2.jpg



Bị lỗi giống hệt trường hợp bên trên


-> Các bạn giải thích giúp mình nguyên nhân với , do câu lệnh mình sai hay do đâu , nếu câu lệnh truy vấn của mình sai thì các bạn sửa giúp mình với mình thanks các bạn rất nhiều

megaownage
18-08-2010, 08:37
Trước khi trả lời, xin phép góp ý với bạn một vài điểm:

1. Cái diagram bạn đưa ra chỉ diễn tả thiết kế CSDL của bạn. Muốn biết đúng hay sai, người ta cần biết thiết kế hoạt động của bạn. VD điều kiện một dơn đặt hàng có nhiều chi tiết món hàng đặt, một phiếu nhập hàng có nhiều chi tiết món hàng nhập, mỗi món hàng nhập liên quan đến một món hàng đặt trước đó. Điểm mà bạn bắt người ta phải đoán là muốn tìm xem một món hàng nhập liên quan đến một món hàng đặt thì phải làm thế nào

2. Nếu bạn copy và đưa lên dữ liệu dạng text thì người ta có thể copy và paste nó lại vào Excel, import qua SQL Server, và chạy thử. Bạn Đăng dữ liệu lên dạng image nên người khác chịu thua.

Trả lời:

Lưu ý phần cuối của câu 1. Muốn tìm xem một món hàng nhập liên quan đến dơn đặt hàng ra sao thì phải tìm ngược về đầu phiếu nhập hàng. Dữ liệu từ chi tiết phiếu nhập không đủ để làm việc này. Đó là điểm sai trong câu truy vấn của bạn. Vì thiếu đầu phiếu nhập, chi tiết nhập bị nối lẫn vào đơn đặt hàng không phải của chúng.

Nói cách khác, bạn phải dùng lô gic nối tuần tự như sau:
Dùng trường sopn nối ctpnhap với pnhap, kế đó dùng trường sodh để nối với dondh, kế đó dùng trường sodh và mavt (phải dùng cả hai trường) để nối với ctdondh. Kết lô gíc
Bây giờ xét lại, bước thứ hai, nối với dondh là thừa, vì sodh của pnhap cũng giống như sodh của dondh (lưu ý: phải giống mới được coi là thừa, cùng trường nhưng khác dữ liệu thì không thừa). Như vậy bạn có thể loại bỏ bước thứ hai. Lô gíc trở thành như sau:
Dùng trường sopn nối ctpnhap với pnhap, kế đó dùng trường sodh và mavt (phải dùng cả hai trường) để nối với ctdondh. Kết lô gíc

Có cái logic này rồi, bạn chỉ việc nối thêm vào các bảng khác để lấy chi tiết.

select x2.sodh, x2.ngaydh, x1.mavt, x3.tenvt, x1.sldat, x1.tongnhap
from
(select c.sodh, c.mavt, c.sldat, sum(a.slnhap) [tongnhap]
from CTPNHAP a inner join PNHAP b on a.sopn = b.sopn
inner join ctdondh c on a.mavt = c.mavt and b.sodh = c.sodh
group by c.sodh, c.mavt, c.sldat) x1
inner join dondh x2 on x1.sodh = x2.sodh
inner join vattu x3 on x1.mavt = x3.matvt

Câu kia cũng dùng logic tương tự

coolboy_9x
18-08-2010, 11:35
trước hết mình xin cảm ơn bạn megaownage vì đã nhiệt tình giúp đỡ mình à
-> Thực ra mình cũng mới học SQL thôi -> mình mới tập tành học truy vấn thôi
-> vì vậy cái diagram ở trên không phải do mình thiết kế
-> cái diagram đó là ở bài tập trong sách có sẵn đi kèm với câu hỏi truy vấn thôi
-> mình làm gì có bản phân tích thiết kế cơ sơ dữ liệu của nó đâu
-> khi làm bài tập đến câu hỏi mình post ở trên ý mình thấy kết quả nó không đúng với , cái chỗ mình khoanh dấu đỏ ý nhẽ ra chỗ đó nó phải = 0 , do dondh đó ko dược nhập ở bảng pnhap ko có dondh D006 , nhưng không hiểu sao nó lại copy dữ liệu tủ bên trên xuống dưới
-> còn cái phần kết nối logic của bạn thực tình mình đọc mãi mà chưa hiểu gì chắc tại kiến thức mình còn yếu
-> còn về phần dữ liệu mình xin tiếp thu ý kiến của bạn mình đã chuyển nó sang dạng text rồi đính kèm với bài trả lời này -> mình mong bạn giúp đỡ mình để mình hiểu ra đươc vấn đề , 1 lần nữa xin cảm ơn bạn :D


Dữ liệu http://www.mediafire.com/?dr5lorvcvcvtjf1

megaownage
18-08-2010, 12:30
Xin lỗi bài trước nói không rõ. Bạn không nhất thiết phải cho tất cả vào Excel, chỉ cần paste dữ liệu dạng text lên bài thôi. Tôi copy qua Excel cũng được. Chủ yếu là dữ liệu dạng gì cũng có cách đổi thành bảng. Trừ dạng image thì tôi chịu thua, không có phần mềm đọc image.

Giải thích logic:
Theo biểu đồ CSDL của bạn thì có thể hiểu thế này:

Thủ kho lập một đơn đặt hàng, trong đơn có nhiều món hàng

Khi nhà cung cấp giao hàng, thủ kho lập một phiếu nhập hàng theo đơn đặt hàng. Cách nhập này quan trọng ở chỗ là mọi phiếu nhập phải có liên hệ đến một đơn đặt hàng. Liên hệ giữa phiếu nhập và đơn đặt hàng là many-to-one (đề bài không nói rõ, nên có thể NCC chỉ giao hàng theo đơn đặt, có thể giao hàng cách khác và thủ kho có bổn phận phải lọc ra nhập theo đơn đặt hàng). Ở đây điểm quan trọng cần để ý là một phiếu nhập chỉ cho phép nhập các món cùng một đơn đặt hàng thôi. Nếu có hai món hàng thuộc về hai đơn đặt hàng khác nhau thì thủ kho phải làm hai phiếu nhập.

Vì vậy một đơn hàng có thể phải qua nhiều phiếu nhập mới thanh toán hết. Tính chất này truyền qua bảng con của đơn hàng, là bảng chi tiết đơn hàng. Nói cách khác, một chi tiết dơn đặt hàng có thể phải trải qua nhiều phiếu nhập mới xong.

Câu truy vấn của bạn chỉ dùng bảng chi tiết nhập hàng nối với bảng chi tiết đơn đặt hàng bị sai là vì nó không phân biệt được món hàng nhập nào thuộc về chi tiết đơn đặt hàng nào. Và kết quả là cứ dòng nào đúng mã vật tư là nó nối. Đọc kết quả, bạn thấy nó liệt kê ra cả các đơn đặt hàng D005, D006 trong khi các đơn này đâu đã bắt đầu nhận hàng (bảng phiếu nhập cho thấy chỉ bắt đầu nhập D001, D002, D003)

Hiểu được vấn đề này rồi, trở lại câu logic đề nghị. Bạn sẽ thấy bảng chi tiết nhập được nối với phiếu nhập với chủ đích xác định món hàng thuộc về đơn đăt hàng nào. Sau khi xác định đựoc đơn đặt hàng, bạn mới có thể nối chính xác với chi tiết đơn đặt hàng. Có sự liên lạc giữa hàng nhập và hàng đặt rồi bạn mới có thể group chúng theo chi tiết đơn hàng và tổng kết được số lượng nhập cho mỗi chi tiết đơn hàng.

Các phần nối còn lại là phần phụ thuộc, dùng để lấy chi tiết món hàng, và ngày đặt hàng.

Lưu ý: câu truy vấn tôi đưa ra chỉ cho biết các món hàng đã có nhận hàng, muốn liết kê ra tất cả đơn hàng thì phải nối hơi khác một chút:

select x2.sodh, x2.ngaydh, x1.mavt, x3.tenvt, x1.sldat, x1.tongnhap
from
(select a.sodh, a.ngaydh, b.mavt
from dondh a inner join ctdondh b on a.sodh = b.sodh) x2
inner join vattu x3 on x1.mavt = x3.matvt
left outer join
(select c.sodh, c.mavt, c.sldat, sum(a.slnhap) [tongnhap]
from CTPNHAP a inner join PNHAP b on a.sopn = b.sopn
inner join ctdondh c on a.mavt = c.mavt and b.sodh = c.sodh
group by c.sodh, c.mavt, c.sldat) x1
on x1.sodh = x2.sodh and x1.mavt = x2.mavt

tiểu lệnh left outer join giúp cho bạn liệt kê cả những món hàng đã đặt nhưng chưa nhận

coolboy_9x
19-08-2010, 22:47
sau 1 hôm ngồi nghiên cứu thì vấn đề đã được sáng tỏ , bài toán đã được giải quyết , mình xin cảm ơn sự giúp đỡ chân thành của bạn megaownage , mình đã hiểu hơn rất nhiều về truy vấn và quan hệ các bảng với nhau , 1 lần nữa thanks bạn megaownage nhé !