Truy vấn bằng SQL dữ liệu từ 2 bảng: bảng tồn và bảng nhập xuất

Liên hệ QC
Với đoạn truy vấn sau sẽ ra kết quả. Tuy nhiên sẽ còn cách khác tối ưu hơn.

SQL:
SELECT ITEM,
       LOTNO,
       STOCKNO,
       Sum(OPENINGSTOCK),
       Sum(STOCKIN),
       Sum(STOCKOUT),
       Sum(OPENINGSTOCK) + Sum(STOCKIN) - Sum(STOCKOUT)
FROM   (SELECT ITEM,
               LOTNO,
               STOCKNO,
               0                                  AS OpeningStock,
               Iif(STOCKTYPE = 'IN', QUANTITY, 0) AS StockIn,
               Iif(STOCKTYPE = 'IN', 0, QUANTITY) AS StockOut
        FROM   [NXT$G2:O29]
        UNION ALL
        SELECT ITEM,
               LOTNO,
               STOCKNOTO,
               0,
               QUANTITY,
               0
        FROM   [NXT$G2:O29]
        WHERE  STOCKTYPE LIKE 'MOV'
        UNION ALL
        SELECT ITEM,
               LOTNO,
               STOCKNO,
               QUANTITY,
               0,
               0
        FROM   [NXT$A2:E6])
WHERE  STOCKNO LIKE 'KHO_004'
GROUP  BY ITEM,
          LOTNO,
          STOCKNO
Cảm ơn bạn đã giúp đỡ,
OT thử trường hợp này kết quả thấy khác với kết quả mong muốn.
Nhờ bạn kiểm tra giúp ạ.
 

File đính kèm

  • NXT_SQL_2.xlsx
    15.6 KB · Đọc: 12
Hi hi!!! Có ràng buộc dữ liệu là lúc nhập liệu á bạn, ở đây là xử lý dữ liệu thô đã có sẵn. Đúng không bạn?
Tôi nói chung về mặt lý thuyết chứ không nói file cụ thể hay dữ liệu cụ thể.
Thực ra bảng 1 trong file trên đây cũng chỉ là file master thứ cấp, chứ không phải master gốc. Master gốc là danh mục mặt hàng chỉ có Mã, tên, đơn vị tính, mô tả thuộc tính. Hết. Mỗi mặt hàng chỉ xuất hiện duy nhất 1 lần.
Bảng master thứ cấp nếu là bảng số tồn như bảng 1 thì 1 mặt hàng có thể xuất hiện nhiều lần: nhiều lot (nhiều lần nhập), tồn ở nhiều kho, thậm chí tồn ở nhiều lần kiểm kê (cột InventoryDate khác nhau).
Vậy bảng master thứ cấp không phải lúc nào cũng có trường khóa để có quan hệ 1 nhiều với bảng khác, chỉ có bảng master gốc mới có thể. Tác giả câu hỏi cũng có thể chưa lường tới vụ này.
 
Tôi nói chung về mặt lý thuyết chứ không nói file cụ thể hay dữ liệu cụ thể.
Thực ra bảng 1 trong file trên đây cũng chỉ là file master thứ cấp, chứ không phải master gốc. Master gốc là danh mục mặt hàng chỉ có Mã, tên, đơn vị tính, mô tả thuộc tính. Hết. Mỗi mặt hàng chỉ xuất hiện duy nhất 1 lần.
Bảng master thứ cấp nếu là bảng số tồn như bảng 1 thì 1 mặt hàng có thể xuất hiện nhiều lần: nhiều lot (nhiều lần nhập), tồn ở nhiều kho, thậm chí tồn ở nhiều lần kiểm kê (cột InventoryDate khác nhau).
Vậy bảng master thứ cấp không phải lúc nào cũng có trường khóa để có quan hệ 1 nhiều với bảng khác, chỉ có bảng master gốc mới có thể. Tác giả câu hỏi cũng có thể chưa lường tới vụ này.
Đúng vậy chú ơi,các item xuất hiện bảng 2 chưa chắc đã có trong bảng 1 và cũng có thể có rất nhiều trong bảng 1.
Dữ liệu master ở bảng khác và đầy đủ các thông tin , mỗi item là duy nhất như chú nêu đó ạ. Các item phải được khai báo ở đây thì mới có dữ liệu ở bảng 1 và 2 được.
Nhưng vì chỉ đơn thuần tính toán nhập xuất tồn theo Item,Lot,Kho không tham chiếu gì đến thông tin khác đến bảng master nên con không đề cập.

Ủa mà chú đổi màu nick rồi ạ.. con chúc mừng chú nha.
 
Nhưng vì chỉ đơn thuần tính toán nhập xuất tồn theo Item,Lot,Kho không tham chiếu gì đến thông tin khác đến bảng master nên con không đề cập.
Vẫn còn 1 thông tin có mà bị bỏ qua (ngoài 3 thông tin tô đỏ): đó là ngày kiểm kê. Một mặt hàng, 1 kho, 1 lot có thể kiểm kê vài lần ở những ngày khác nhau.
 
Vẫn còn 1 thông tin có mà bị bỏ qua: đó là ngày kiểm kê. Một mặt hàng, 1 kho, 1 lot có thể kiểm kê vài lần ở những ngày khác nhau.
Dạ vâng đúng như vậy ạ, nếu là lấy từ cơ sở dữ liệu ban đầu thì là vậy nhưng là bởi vì khi truy vấn ngày tháng để lấy dữ liệu về con đã chọn tháng kiểm kê cùng từ ngày đến ngày nhập xuất rồi nên dữ liệu nằm trọn trong đó và coi như có thể bỏ qua mà chỉ xét phần tính toán thôi ạ,
Bài đã được tự động gộp:

Bạn chưa thấy dữ liệu gốc bao giờ.
Bảng 1: Dữ liệu tồn kho bao giờ cũng có: Nhiều kho, nhiều mặt hàng, mỗi kho nhiều mặt hàng, mỗi mặt hàng nhiều kho, mỗi mặt hàng nhiều lot nhập về.
Bảng 2: dữ liệu phát sinh (hàng ngày) cũng nhiều dạng như vậy và nhân lên nhiều ngày.
Không có trường khóa tạo quan hệ là chết chắc.
Mấu chốt CSDL bắt buộc phải vậy chứ phát sinh nhập xuất lot này, kho này mà lấy tồn đầu kho khác, lot khác là báo cáo vứt đi ngay.

Đúng vậy, tôi chỉ gợi ý. Đã biết SQL, hỏi trong chủ đề SQL, thì đáng lẽ chỉ gợi ý vậy thôi là làm được.
Đúng rồi chú, đây là dữ liệu nhiều mã kho nhiều mặt hàng và tổng hợp tất cả những gì nó có ạ.
 

File đính kèm

  • NXT_SQL_3.xlsx
    67.8 KB · Đọc: 12
Lần chỉnh sửa cuối:
Đúng vậy chú ơi,các item xuất hiện bảng 2 chưa chắc đã có trong bảng 1 và cũng có thể có rất nhiều trong bảng 1.
Dữ liệu master ở bảng khác và đầy đủ các thông tin , mỗi item là duy nhất như chú nêu đó ạ. Các item phải được khai báo ở đây thì mới có dữ liệu ở bảng 1 và 2 được.
Nhưng vì chỉ đơn thuần tính toán nhập xuất tồn theo Item,Lot,Kho không tham chiếu gì đến thông tin khác đến bảng master nên con không đề cập.
...
Table1 của bạn ở trên là Master File.
Key chính của nó là Item+LotNo+StockNo (key kép).
Ở đâu dó, bạn có file TableX với key chính là Item, TableY với key chính là Item+LotNo thì chúng chỉ là hai bảng khác của Item, không ảnh hưởng gì đến hoạt động Mater~Transaction giữa Table1 và Table2 trong bài này.
Mỗi dòng trong Table2 là một transaction (phát sinh). Mỗi transaction mang một key để liên hệ nó với Table1. Ở đây cái key ấy là Item+LotNo+StockNo.
Lưu ý quan trọng: master file có thể mang điều kiện mỗi key là duy nhất, nhưng transaction file không hề bắt buộc. Một khóa Item+LotNo+StockNo có thể có nhiều transactions (liên hệ 1-N).
Đó là lý do khi tổng kết transactions, người ta thường có thêm đoạn Group by. Nếu trong bảng Table2, bạn bảo đảm được khóa Item+LotNo+StockNo là duy nất thì không cần phải Group.

SQL là ngôn ngữ được đặt ra để truy vấn CSDL LH. Cách thông dụng nhất để thực hiện LH (liên hệ) là dùng khóa (key).

Khi tôi nói Table2 của bạn không thiết kế đúng chuẩn thì từ "chuẩn (normalised)" ở đây nằm trong ngữ cảnh của CSDL LH. Tiếng Anh gọi là Level of Normalisation. Vì bảng này không thống nhất kiểu transaction - IN/OUT chỉ lả transaction đơn nhưng MOV là kép, bao gồm 1 IN và 1 OUT. Và CSDL như thế không đạt được cả chuẩn bậc 1. Thiết kế lý tưởng thì thường đạt đến bặc 3.

Những gì tôi giải thích cho bạn ở đây thuộc về tầm sâu của lý thuyết SQL (Structured Query Language) và CDSL LH (Relational DataBase). Nói chuyện tầm sâu thì phải chính xác. Tôi không biết tầm rộng cần gì và cũng không muốn nói chuyện tầm rộng.
 
Table1 của bạn ở trên là Master File.
Key chính của nó là Item+LotNo+StockNo (key kép).
Ở đâu dó, bạn có file TableX với key chính là Item, TableY với key chính là Item+LotNo thì chúng chỉ là hai bảng khác của Item, không ảnh hưởng gì đến hoạt động Mater~Transaction giữa Table1 và Table2 trong bài này.
Mỗi dòng trong Table2 là một transaction (phát sinh). Mỗi transaction mang một key để liên hệ nó với Table1. Ở đây cái key ấy là Item+LotNo+StockNo.
Lưu ý quan trọng: master file có thể mang điều kiện mỗi key là duy nhất, nhưng transaction file không hề bắt buộc. Một khóa Item+LotNo+StockNo có thể có nhiều transactions (liên hệ 1-N).
Đó là lý do khi tổng kết transactions, người ta thường có thêm đoạn Group by. Nếu trong bảng Table2, bạn bảo đảm được khóa Item+LotNo+StockNo là duy nất thì không cần phải Group.

SQL là ngôn ngữ được đặt ra để truy vấn CSDL LH. Cách thông dụng nhất để thực hiện LH (liên hệ) là dùng khóa (key).

Khi tôi nói Table2 của bạn không thiết kế đúng chuẩn thì từ "chuẩn (normalised)" ở đây nằm trong ngữ cảnh của CSDL LH. Tiếng Anh gọi là Level of Normalisation. Vì bảng này không thống nhất kiểu transaction - IN/OUT chỉ lả transaction đơn nhưng MOV là kép, bao gồm 1 IN và 1 OUT. Và CSDL như thế không đạt được cả chuẩn bậc 1. Thiết kế lý tưởng thì thường đạt đến bặc 3.

Những gì tôi giải thích cho bạn ở đây thuộc về tầm sâu của lý thuyết SQL (Structured Query Language) và CDSL LH (Relational DataBase). Nói chuyện tầm sâu thì phải chính xác. Tôi không biết tầm rộng cần gì và cũng không muốn nói chuyện tầm rộng.
Khổ cho con quá, đây là CSDL của bên phần mềm thiết kế bác ơi. Cái tên trường của họ đặt như thế nào con cũng bê nguyên như vậy bác ạ. Thôi thì họ muốn đặt tên là gì cũng được với con chỉ cần cái code để gọi là được bác.
Bác giúp con câu lệnh hoàn chỉnh với con vẫn đang loay hoay mà chưa ra ạ...
Có lẽ theo gợi ý của bác Hiếu con dùng VBA cho dễ ^^
 
Table1 của bạn ở trên là Master File.
Tôi còn gọi là master thứ cấp, vì phải dùng key là 3 field gộp lại, nếu master cấp 1 (danh mục) thì item phải là duy nhất và dùng làm trường khóa luôn.
IN/OUT chỉ lả transaction đơn nhưng MOV là kép, bao gồm 1 IN và 1 OUT.
Đó gọi là tiết kiệm không gian nhưng sẽ bị thiệt về thời gian khi cần tách ra. Không những vậy, nó còn không diễn tả được các trường hợp đặc biệt như sau:
1. Hao hụt mất mát khi chuyển kho: gói kẹo mang từ phòng này qua phòng kia còn bị mất mát nữa là hàng chuyển từ kho nọ qua kho kia phải qua khâu vận chuyển
2. Hàng chuyển kho đã xuất ra khỏi kho đi, nhưng còn đang trên đường, chưa đến kho nhận. Kho nhận chưa thể ghi nhận tăng số lượng. Nếu nhằm ngày cuối tháng, tệ hơn là nhằm ngày cuối năm tài chính thì kiểm kê thiếu hụt cả tỷ tiền hàng.

Cách giải quyết:
- tách 2 chứng từ giao dịch: xuất chuyển kho và nhập chuyển kho
- Mỗi chứng từ có số lượng theo yêu cầu và số thực tế
- Có kho trung gian gọi là kho đi đường (kho ảo). KIểm kê kho ảo mà còn tồn tức là: một: hàng chưa đến, hai: nếu hàng đã đến mà thực nhận ít hơn, hàng mất mát tổn thất trên đường đi.
 
...
Có lẽ theo gợi ý của bác Hiếu con dùng VBA cho dễ ^^
Anh ấy nói đúng. Trường hợp này dùng con bài cũ Đít sần tốt hơn nhiều.

ADO sử dụng SQL, mà SQL thì CSDL phải đạt ít nhất là chuẩn bậc 2 mới dễ hoạt động. Table2 của bạn chưa đạt được bậc 1 (cán dẹp/flatten - tức không có chuyện phát sinh kép) cho nên chính câu SQL phải làm chuyện "cán dẹp" này.
Tôi không muốn viết câu SQL cho bài này vì nó khá phức tạp mà tôi không nghĩ là bạn học được bao nhiêu (vì nó quá đặc thù).
 
Cảm ơn bạn đã giúp đỡ,
OT thử trường hợp này kết quả thấy khác với kết quả mong muốn.
Nhờ bạn kiểm tra giúp ạ.
Như tôi đã nói là bạn phải miêu tả từng trường hợp cụ thể. Tôi không rành về VBA nên không có hiểu code bạn viết nó như thề nào.
 
Bạn phải miêu tả là làm sao ra được số lượng StockIn và StockOut nha hôn.
Như tôi đã nói là bạn phải miêu tả từng trường hợp cụ thể. Tôi không rành về VBA nên không có hiểu code bạn viết nó như thề nào.
Thật khâm phục bạn, khi chưa hiểu bản chất mà vẫn có thể viết được câu lệnh truy vấn.
Vậy OT lấy file bài 225:
để giải thích = công thức ạ:

T3 = SUMIFS($D$3:$D$6,$A$3:$A$6,$Q3,$B$3:$B$6,$S3,$C$3:$C$6,$R3)

U3 = SUMIFS($N$3:$N$29,$H$3:$H$29,$Q3,$J$3:$J$29,$S3,$M$3:$M$29,$R3,$G$3:$G$29,"IN")
+SUMIFS($N$3:$N$29,$H$3:$H$29,$Q3,$I$3:$I$29,$S3,$M$3:$M$29,$R3,$G$3:$G$29,"MOV")

V3 = SUMIFS($N$3:$N$29,$H$3:$H$29,$Q3,$J$3:$J$29,$S3,$M$3:$M$29,$R3,$G$3:$G$29,"OUT")
+SUMIFS($N$3:$N$29,$H$3:$H$29,$Q3,$J$3:$J$29,$S3,$M$3:$M$29,$R3,$G$3:$G$29,"MOV")

W3 = T3+U3-V3
 
Nếu bảng 1 có trường khóa như sau:

1687618282271.png

Bảng 2 có trường khóa như sau:

1687618323367.png

Thì câu SQL sẽ là:

Mã:
SELECT NXT.*, iif([Opening] <> 0 ,[Opening],0)+[QtyIn]-[QtyOut] AS Ending
FROM
(SELECT Data.Item, Data.LotNo, "Kho_004" as WH, Ton.Quantity AS Opening,
Sum(IIf([StockType]="IN" Or ([StockType]="Mov" And [Data].[StockNoTo]="KHO_004"),[DAta].[Quantity],0)) AS QtyIn,
Sum(IIf([StockType]="OUT"   Or ([StockType]="Mov" And [Data].[StockNo]="KHO_004"),[DAta].[Quantity],0)) AS QtyOut
FROM Data LEFT JOIN Ton ON Data.ID = Ton.ID
GROUP BY Data.Item, Data.LotNo, Ton.Quantity) NXT;

Kết quả (làm trong Access):

1687620705427.png
 
Lần chỉnh sửa cuối:
Nếu bảng 1 có trường khóa như sau:

View attachment 291918

Bảng 2 có trường khóa như sau:

View attachment 291919

Thì câu SQL sẽ là:

Mã:
SELECT NXT.*, iif([Opening] <> 0 ,[Opening],0)+[QtyIn]-[QtyOut] AS Ending
FROM
(SELECT Data.Item, Data.LotNo, "Kho_004" as WH, Ton.Quantity AS Opening,
Sum(IIf([StockType]="IN" Or ([StockType]="Mov" And [Data].[StockNoTo]="KHO_004"),[DAta].[Quantity],0)) AS QtyIn,
Sum(IIf([StockType]="OUT"   Or ([StockType]="Mov" And [Data].[StockNo]="KHO_004"),[DAta].[Quantity],0)) AS QtyOut
FROM Data LEFT JOIN Ton ON Data.ID = Ton.ID
GROUP BY Data.Item, Data.LotNo, Ton.Quantity) NXT;

Kết quả (làm trong Access):

View attachment 291921
Câu lệnh này chạy trong môi trường SQL hay ADO thì sửa lại thế nào vậy chú Mỹ .
Con không có Access ạ.
 
Câu lệnh này chạy trong môi trường SQL hay ADO thì sửa lại thế nào vậy chú Mỹ .
Con không có Access ạ.
SQL là một ngôn ngữ được tiêu chuẩn hóa để truy vấn CSDL LH. Chả có môi trường nào gọi là SQL cả. Mõi môi trường có một phiên bản riêng của chúng. Ví dụ Access thì dùng Access Query, SQL Server thì dùng TSQL, Oracle thì dùng PL-SQL (hay SQL-Plus)
ADO (Active Data Object) là một Object của MS. Trong VBA, ADO dùng để kết nối với CSDL và truy vấn. Nếu kết nối với Excel thì phải dùng cổ máy Access để truy vấn cho nên câu truy vấn phải viết theo Access. Nếu kết nối vói SQL Server thì câu truy vấn viết theo TSQL.

Chỉnh:
1. Đặt mỗi dòng vào giữa cặp "".
2. Đầu mỗi dòng, chèn thêm một dấu cách giữa " và ký tự đầu tiên.
3. Cuối mỗi dòng, trừ dòng cuối, chèn thêm & _ (dấu ampersand, một dấu cách, và dấu gạch dưới)
4. Trong dòng, bất cứ chỗ nào có " thì đổi nó thành ""
Như vậy câu thứ 3 sẽ là
" SELECT Data.Item, Data.LotNo, ""Kho_004"" as WH, Ton.Quantity AS Opening," & _
Và dòng cuối là
" GROUP BY Data.Item, Data.LotNo, Ton.Quantity) NXT;"

1. Lập chuỗi để cho vào chuỗi sqlStr
2. Dấu cách là mẹo viết SQL string, dùng để bảo đảm nối chuỗi thì không bị dính chữ.
3. Ngữ pháp VBA: & là toán tử nối chuỗi, _ là bảo trình dịch rằng "dòng này chưa xong, cần nối với dòng tiếp theo"
4. Ngữ pháp VBA: Bên trong cặp "" thì bất cứ " nào cũng phải đổi thành "", nếu có "" thì đổi thành """"
 
Lần chỉnh sửa cuối:
SQL là một ngôn ngữ được tiêu chuẩn hóa để truy vấn CSDL LH. Chả có môi trường nào gọi là SQL cả. Mõi môi trường có một phiên bản riêng của chúng. Ví dụ Access thì dùng Access Query, SQL Server thì dùng TSQL, Oracle thì dùng PL-SQL (hay SQL-Plus)
ADO (Active Data Object) là một Object của MS. Trong VBA, ADO dùng để kết nối với CSDL và truy vấn. Nếu kết nối với Excel thì phải dùng cổ máy Access để truy vấn cho nên câu truy vấn phải viết theo Access. Nếu kết nối vói SQL Server thì câu truy vấn viết theo TSQL.

Chỉnh:
1. Đặt mỗi dòng vào giữa cặp "".
2. Đầu mỗi dòng, chèn thêm một dấu cách giữa " và ký tự đầu tiên.
3. Cuối mỗi dòng, trừ dòng cuối, chèn thêm & _ (dấu ampersand, một dấu cách, và dấu gạch dưới)
4. Trong dòng, bất cứ chỗ nào có " thì đổi nó thành ""
Như vậy câu thứ 3 sẽ là
" SELECT Data.Item, Data.LotNo, ""Kho_004"" as WH, Ton.Quantity AS Opening," & _
Và dòng cuối là
" GROUP BY Data.Item, Data.LotNo, Ton.Quantity) NXT;"

1. Lập chuỗi để cho vào chuỗi sqlStr
2. Dấu cách là mẹo viết SQL string, dùng để bảo đảm nối chuỗi thì không bị dính chữ.
3. Ngữ pháp VBA: & là toán tử nối chuỗi, _ là bảo trình dịch rằng "dòng này chưa xong, cần nối với dòng tiếp theo"
4. Ngữ pháp VBA: Bên trong cặp "" thì bất cứ " nào cũng phải đổi thành "", nếu có "" thì đổi thành """"
Con sửa như thế mà không chạy được , bác xem giúp con với:
Mã:
    query = "SELECT NXT.*, iif([Opening] <> 0 ,[Opening],0)+[QtyIn]-[QtyOut] AS Ending " & _
            "FROM (SELECT Data.Item, Data.LotNo, 'Kho_004' as WH, Ton.Quantity AS Opening, " & _
                "Sum(IIf([StockType]='IN' Or ([StockType]='Mov' And Data.[StockNoTo]='KHO_004'),Data.[Quantity],0)) AS QtyIn, " & _
                "Sum(IIf([StockType]='OUT' Or ([StockType]='Mov' And Data.[StockNo]='KHO_004'),Data.[Quantity],0)) AS QtyOut " & _
            "FROM [NXT$G2:O29] Data LEFT JOIN [NXT$A2:E6] Ton ON Data.ID = Ton.ID " & _
            "GROUP BY Data.Item, Data.LotNo, Ton.Quantity) NXT;"
 
Làm việc từng giai đoạn một.
Đã thử
" Sectect *" & _
" FROM [NXT$G2:O29] Data LEFT JOIN [NXT$A2:E6] Ton ON Data.ID = Ton.ID "
Xem nó ra cái gì?

Chú ý:
Để bảo đảm không bị dính chữ khi nối hai câu, tôi đặt dấu cách ở đầu câu. Đặt ở cuối câu cũng được (có người nói tốt hơn) nhưng tôi có tật lười scroll qua bên phải để xem và kiểm định nó.
 
Làm việc từng giai đoạn một.
Đã thử
" Sectect *" & _
" FROM [NXT$G2:O29] Data LEFT JOIN [NXT$A2:E6] Ton ON Data.ID = Ton.ID "
Xem nó ra cái gì?

Chú ý:
Để bảo đảm không bị dính chữ khi nối hai câu, tôi đặt dấu cách ở đầu câu. Đặt ở cuối câu cũng được (có người nói tốt hơn) nhưng tôi có tật lười scroll qua bên phải để xem và kiểm định nó.
Con thử thấy lỗi "Invalid SQL statement; expected 'DELETE', 'INSERT', 'PROCEDURE', 'SELECT', or 'UPDATE'."
Và con cũng thử câu lệnh này:
Mã:
query = "SELECT Data.Item, Data.LotNo, 'Kho_004' AS WH, Ton.Quantity AS Opening, " & _
        "Sum(IIf([StockType]='IN' Or ([StockType]='Mov' And Data.[StockNoTo]='KHO_004'), Data.[Quantity], 0)) AS QtyIn, " & _
        "Sum(IIf([StockType]='OUT' Or ([StockType]='Mov' And Data.[StockNo]='KHO_004'), Data.[Quantity], 0)) AS QtyOut " & _
        "FROM [NXT$G2:O29] AS Data " & _
        "LEFT JOIN [NXT$A2:E6] AS Ton ON Data.ID = Ton.ID " & _
        "GROUP BY Data.Item, Data.LotNo, Ton.Quantity;"

cũng lỗi:
No value given for one or more required parameters.
 
Web KT
Back
Top Bottom