Truy vấn trong SQL?
Xin chào các bạn.
OT chạy câu lệnh sau:SELECT sc.name + '.' + ta.name TableName, SUM(pa.rows) RowCnt FROM sys.tables ta INNER Join sys.partitions pa ON pa.OBJECT_ID = ta.OBJECT_ID INNER Join sys.Schemas sc ON ta.schema_id = sc.schema_id WHERE ta.is_ms_shipped = 0 AND pa.index_id IN (1,0) Group BY sc.name, ta.name Order BY Sum (pa.Rows) DESCKết quả trả về tên bảng và số dòng của bảng và sắp xếp giảm giần theo cột số dòng trong bảng.
SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.ColumnsKết quả trả về tên bảng và tên các cột trong bảng.
Xin hỏi có câu lệnh nào để trả về 3 dữ liệu: tên bảng, tên cột trong bảng, số dòng trong cột?
"Số dòng trong cột" là như thê nào nhỉ?
thường thì mình nói về số dòng của bảng, vì ô mà không có dữ liệu (NULL) thì vẫn là một ô.
Cái này là tư duy của range, bảng trong excel-vba nên bỏ đi
Khi đã quan niệm là theo Cơ sở dữ liệu – thì đối tượng quan tâm chính nên là Data (dữ liệu) và đối tượng xử lý là table, field, recordset, … và Relationship…
Schema là metadata.
Xáo trộn giữa metadata và data là công việc của data manager hoặc desinger.
Đây là công việc cao cấp. Thường thì sau khi hệ thống phần mềm đưa vào hoạt động cỡ 1 năm (hay 6 tháng, tuỳ theo độ lớn) thì data designer sẽ bắt đầu lập thống kê dữ liệu để hiệu chỉnh lại metadata.
Như đã nói, làm công việc này là hàng cao cấp cho nên ông nội tôi cũng không dám xía vào. Công việc không phải chỉ viết 1 cái sp rồi đọc kết quả. Từ khoá ở đây là "hiệu chỉnh".
Xin chào anh Bình,
Đúng rồi thường là sẽ nói về số dòng của bảng bảng cột nào nhiều dòng nhất thì sẽ lấy số dòng của cột đó.
Ở đây OT muốn lấy dữ liệu của các ô có dữ liệu của các cột trong bảng như minh họa ảnh kèm bên dưới ạ.Mục đích cũng chỉ là hỏi để xem có câu lệnh này không?
Và OT muốn sử dụng câu lệnh này để kiểm tra thông tin thôi ạ.
Mong anh và mọi người xem giúp ạ.[ATTACH type="full" alt="Untitled (2).jpg"]2503
Theo như hình của bạn, thông tin vừa lấy từ các table hệ thống vừa truy vấn số dòng NOT NULL trong từng table riêng nên tôi nghĩ là không có cách join các table để lấy thông tin trực tiếp như bạn yêu cầu mà phải dùng cách đi vòng: tạo table tạm lưu thông tin (Tên bảng, Tên Cột, Ô có dữ liệu) rồi mới cập nhật dữ liệu vào table này. Các bạn chuyên về SQL Server có cách khác thì hỗ trợ giùm nhé.
Cách tôi làm như sau: Vì bạn chủ yếu muốn thống kế nên tôi làm kiểu thủ công trực tiếp trong SQL Server nhé.
1. Tạo table tạm:
USE NORTHWIND --Đổi tên Database của bạn.
GO
CREATE TABLE myDBInfo (
TblName VARCHAR(30),
ColName VARCHAR(30),
NumRow INT
);
2. Insert dữ liệu từ INFORMATION_SCHEMA.COLUMNS vào table tạm:
USE NORTHWIND
GO
INSERT INTO myDBInfo SELECT TABLE_NAME, COLUMN_NAME,0 FROM INFORMATION_SCHEMA.COLUMNS
3. Tạo các stored proc. (SP) để thực thi việc cập nhật dữ liệu: tạo 2 SP
– SP: UpdatemyDBInfoTbl
USE [NORTHWIND]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[UpdatemyDBInfoTbl]
@TName nvarchar(30),
@CName nvarchar(30)
AS
BEGIN
SET NOCOUNT ON;
Declare @sql nvarchar(300);
Set @sql='UPDATE myDBInfo SET NumRow = (SELECT count(*) FROM ' + @TName + ' WHERE ' + @CName + ' Is Not Null) WHERE myDBInfo.TblName =''' + @TName + ''' AND myDBInfo.ColName =''' + @CName + ''''
EXEC sp_executesql @sql
--print @sql
END
– SP: GetNumRowNotNull
USE [NORTHWIND]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[GetNumRowNotNull]
AS
BEGIN
declare @TName varchar(30)
Declare @CName varchar(30)
declare cur CURSOR LOCAL for
select TblName, ColName from myDBInfo
open cur
fetch next from cur into @TName, @CName
while @@FETCH_STATUS = 0 BEGIN
--print @TName
--print @CName
--Chạy Store Proc. cho từng dòng
exec dbo.UpdatemyDBInfoTbl @TName, @CName
fetch next from cur into @TName, @CName
END
close cur
deallocate cur
END
==> Xong. Bây giờ chạy lệnh thực thi SP trên.
Exec sp_executesql GetNumRowNotNull
Và xem kết quả:
select * from mydbinfo
2504
– Trong Excel bạn dùng ADO Command để gửi lệnh yêu cầu SQL Server thực thi cái stored proc. "GetNumRowNotNull".
– Sau đó bạn dùng ADO Recordset để lấy dữ liệu từ table "myDbInfo" về Excel sheet như cách bạn đang làm.
– Một cái quan trọng để tránh lỗi cho cái SP trong SQL server là đặt tên Table, tên Field không có khoảng trắng nhé.
www.giaiphapexcel.com/diendan/threads/truy-v%E1%BA%A5n-trong-sql.143453/
Thiết kế Tổng đãi ngộ (Total Rewards) theo khung SHRM
Khóa học “Thiết kế Tổng phần thưởng (Total Reward) chuẩn khung SHRM” giúp bạn nắm vững toàn bộ hệ thống đãi ngộ theo chuẩn...
Xem khóa học
Em chạy code sau để cập nhật lại cái SP "GetNumRowNotNull".
Sau này chỉ cần chạy cái SP trên, nó sẽ xoá nội dung table myDBInfo (không xoá table), cập nhật lại tên table, column sau đó cập nhật số dòng.
Bạn thử
select CODE,CDATE,QTY from SODER where cdate >='01/09/2019' and cdate < '01/10/2019'
– Dùng hàm DateSerial() nhé bạn.
– Không được dùng các từ khoá của hệ thống làm tên Fieldm tên biến. "CDate"
SELECT Code, Ngay, Qty, DateSerial(Left(,4),Mid(,5,2),Right(,2)) As NgayChuyen FROM SORDER WHERE Between #" & txtTuNgay & "# AND #" & txtDenNgay & "#"
Oh. Em xài SQL Server 2008 à? Em thay thế hàm Mid bằng hàm SubString đi.
muốn truy vấn chuẩn thì đầu tiên phải biết datatype của các cột là gì nhé.
t-sql thì: select … cast( as date) as xx where fieldate between '2019-07-01' and '2019-07-31'
T-SQL:
CDATE Like '201907%'
CDATE Like '201907__'
🙂 Lỗi do anh lẫn lộn giữa hàm bên VBA và SQL Server, râu ông nọ cắm cằm bà kia.
Em phải đổi NVarchar thành DateTime thì mới thực hiện các phép so sánh + – ngày tháng chính xác.
Dùng hàm DateFromParts() tương tự hàm DateSerial() trong VBA. Ngắn gọn là dùng CAST hoặc CONVERT.
Convert(nvarchar, CDATE, 23)
SELECT CODE, CDATE, QTY FROM SORDER WHERE Convert(nvarchar,CDATE,23) between '2019-09-01' And '2019-10-01'
kiểm tra mới chắc chắn đc nhé, vì trong nhiều trường sẽ xảy ra trường hợp tự ép kiểu nhé. mình dùng điện thoại nên không xem cụ thể thế nào nhưng qua phỏng đoán code trên thì cột của bạn là yyyymmdd và nó là varchar chứ không là date, date trong ms sql là yyyy-mm-dd, trong th của bạn là ép kiểu rồi.
bạn chạy câu lệnh là biết date trong ms sql fortmat chuẩn ntn: select getdate()
bạn sử dụng hàm cast thôi cast(cdate as date) between x and y. còn k bạn k cần cast thì nó tự ép kiểu cho bạn
Trường [Ngày tháng] không có sao bạn OT?
Nếu dữ liệu tồn kho, đơn hàng mấy năm thì máy chạy mệt à.
Tôi hỏi kỹ để tránh việc đưa một câu lênh T-SQL mà kết quả của nó không có ý nghĩa gì hết, rồi em áp dụng cũng không được.
Cái mấu chốt nằm ở cái table STOCK của em. Nó là tồn kho ngay tại thời điểm chạy query hay tồn đầu kỳ (từng tháng).
– Nếu là tồn đầu kỳ thì đưa vào truy vấn số lượng bán (tôi suy ra theo cái tên SOrder – Sales Order) tồn kho không chính xác vì còn phải + thêm nhập TK tính tới ngày xuất bán -> lúc đó mới có ý nghĩa: đối chiếu với tồn kho thời điểm (Quantity On Hand) trước khi xuất bán.
– Nếu đó là table tồn kho thời điểm xét thì không có gì để nói. 🙂
– Có trường hợp "MH001" bán cho các khách hàng khác không? vd KH002, KH005… Khi nhìn table KHACHHANG tôi lại nghĩ nó giống Nhà Cung Cấp và cái SORDER trở thành table Mua hàng (PURCHASE ORDER) hơn. Khi đó lại sẽ phát sinh các vấn đề khác về tổ chức lưu thông tin (hoặc do em cung cấp thông tin table liên quan quá ít nên không nhìn thấy tổ chức tổng thể của CSDL).
Nếu cái bảng kết quả em muốn là tồn kho và số lượng đặt hàng của từng nhà cung cấp thì table STOCK thiếu thông tin Mã NCC của từng Mã hàng tồn kho.
Nếu nói mỗi Mã Hàng chỉ có 1 NCC cố định nên gán Mã Hang đi theo NCC rồi như table KHACHANG, truy vấn từ Mã hàng sẽ ra mã NCC thì cũng sai vì chỉ nhìn ngắn hạn. Sau này có đổi mua của NCC khác thì theo dõi như thế nào? tồn kho NCC cũng, tồn kho NCC mới…
Tại tôi muốn hiểu rõ chút về quan hệ giữa các Table, các field như thế nào và thông tin từ em cung cấp cũng không nhiều nên hỏi tùm lum là vậy rồi mới ra được câu lệnh truy vấn. Chứ để ra kết quả như trên thì không có gì phức tạp.
Nếu chỉ đơn giản là tham khảo thì em thử câu lệnh này:
– Theo như hình của em, anh lấy trường từ table DSSANPHAM.
– Nếu để đối chiếu tồn kho với table xuất hàng (SORDER) thì trường mã SP phải lấy từ table SORDER, khi đó câu lệnh phải đổi lại là:
Tôi có nói rõ là nó rất rắc rối. Không thể tư vấn theo kiểu diễn đàn được. Bắt buộc phải ăn dầm nằm dề tại kho mà quan sát từng công việc.
Việc cốt kiếc này nọ là chuyện tay trái của tôi cho nên tôi có thể sẵn sàng làm.
Nhưng thiết kế CSDL cho Inventory Control thì tôi không sẵn sàng. Không phải tôi giấu nghề, nhưng tư vấn mà không biết rõ quy trình và không chủ động được quy trình thì tôi từ chối.
Tôi không hề mắc cở khi có ngừoi nói "thằng VM viết code rác rưởi này à?".
Nhưng tôi không chấp nhận một ngày nào đó, có người nói "thằng VM thiết kế cái CSDL rác rưởi này à?"
(*) chủ động quy trình có nghĩa là nếu tôi nói "làm như thế này mới đúng" thì cơ quan phải làm như thế; không có chuyện "nhưng mà…"
Nếu CSDL đã có kết chuyển tồn cuối kỳ (hoặc tồn đầu) theo tháng và tồn tại thời điểm rồi thì chắc chắn là đã có giải thuật tính tồn kho theo khoảng thời gian cần truy vấn rồi. Chắc là bạn chưa biết nó nằm trong cái stored proc. nào để gọi ra thôi.
Chắc là ý em OT muốn lấy báo cáo Nhập – Xuất – Tồn trong một khoảng thời gian nhưng không diễn giải đúng đó anh VetMini. Tồn kho ở từng thời điểm nhâp xuất.
Có những ngôn từ hơi nóng về chính trị một chút.
Người "anh hùng" có thể ỷ mình bất khả xâm phạm nhưng kẻ "trượng phu" phải biết suy nghĩ cho hoàn cảnh của người khác.
Tính tồn kho thời điểm đã qua thì không khó lắm.
Nếu là SQL Server (chính bản, không phải Express) thì người thiết kế thường có cái view cho biết tồn kho ở từng đầu kỳ. Ví dụ tôi ở tài khoá 2019 thì tôi sẽ có 12 cái views của 12 tháng 2018, và 8 cái views cho tháng 1-8 2019.
Việc tính tồn kho từng thời điểm chỉ là truy vấn cái view đúng đầu kỳ và cộng/trừ đi những phát sinh cho đến thời điểm cần tính.
Nếu không có những cái views này thì:
1. Bảo người thiết kế viết sp để thiết lập chúng, HOẶC
2. Chịu khó mò cái tồn kho gần nhất. Và làm tương tự như trên
Tính tồn kho dự toán tương lai thì mới khó. Vì phải tính tình trạng từng hợp đồng đã ký, hoặc dự định ký nhưng chưa xuất kho.
(có một số hệ thống xuất kho rồi vẫn tính là hàng còn trong tay, bên kia nhận rồi mới tính là hàng không còn của mình)
Cảm ơn Bác VetMini , Anh ongke0711 đã luôn quan tâm & giúp đỡ OT ạ.
OT cũng chưa nghiên cứu được dữ liệu trong CSDL ở các bảng liên quan với nhau như thế nào nên chưa đưa dữ liệu lên được.
Bác và Anh có tài liệu hoặc biết link nào tiếng Việt về CSDL/ liên quan cụ thể đến quản lý kho không ạ gửi cho OT thử "nghịch" với được không ạ.
Híc anh IT cấm không cho OT sử dụng câu lệnh nào ngoài câu lệnh SELECT trong DB thật ạ, còn muốn làm gì thì anh ý cũng tạo ra một DB bản sao cho nghịch mà OT cũng chưa biết nên bắt đầu từ đâu ạ.
Khổ có trường, có nơi thực hành nhưng không có Thầy ạ T_T
Thay số 0 thành tên field tưng ứng cần chuyển đổi.
Cast (Tên field As Decimal…..)
Đúng như bạn ppc0312 đã đề cập, thường câu lệnh này chỉ là trung gian trong một truy vấn gì đó như Union query, stored proc… chứ câu lệnh này không phải để em thay tên field. Anh gợi ý cách thay tên field để em hiểu về cú pháp và để truy vấn ra số tồn kho.
Muốn hiểu hơn thì phải có toàn bộ đoạn code trên mới phán đoán được.
sử dụng
Recordset.RecordCount
sử dụng rowcount và phần chay truy vấn với tham số
rs.Open strSQL, conn,3,1
Mình k nhớ có chính xác k.
RecordCount trong ADO Recordset chỉ chạy được với 3 loại "CursorType" là: adOpenKeySet (1), adOpenDynamic (2), adOpenStatic (3)
CursorType: adOpenForwardOnly(0) nó không đọc được nên trả về giá trị -1, tức là cho biết có record tồn tại thôi.
Nếu chuỗi kết nối không khai báo thì ADO sẽ sử dụng CursorType mặc định là: adOpenForwardOnly – 0
🙂 Em dùng câu lênh như của quanluu1989 đó. Anh chỉ giải thích thêm là phải khai báo Recordset theo kiểu CursorType đó thì RecordCount mới trả về kết quả đúng.
Cách 1: dùng khai báo sớm nhé. (Early Binding)
Cách 2: như của quanluu1989
Lỗi này do cái ConnectString của bạn bị sai nên không open được
Xem lại cái Chr(39) trong chuỗi Connect. Nếu nhớ không nhầm thì Chr(39) là dấu nháy đơn (') thì phải
@OT thử, điều kiện là các ngày đều trong quá khứ và hiện tại
Hỏi thêm:
– Data luôn được sắp xếp cột A (Date) từ nhỏ đến lớn?
– Trong Data có khi nào có ngày lớn hơn ngày hiện tại (Today()) không? Nếu có thì trước 1 ngày hoặc sau 1 ngày hiện tại thì lấy ngày nào?
– Số 20200299 thể hiện điều gì (Từ dòng 18594)
Như vậy lúc nào ngày ở dòng cuối luôn là ngày gần nhất.
Cứ Filter ngày này là ra thôi.
Câu truy vấn là Select * from data where date=(select….)
Chính là biến s ở bài của mình.
Nếu có "20200331" và "20200399" ngày gần nhất là ngày nào?
Có 2 ngày "20200229" và "20200299"
Ví dụ dữ liệu chỉ tới tháng 2 năm 2020, ngày cuối sẽ là ngày nào?
Rắc rối rồi, SQL bài trước phải viết lại
Thử code
Cái này phải bắt buộc nhập chuẩn dữ liệu từ phần mềm, chứ chẳng ai để như thế này cả, rất khó xử lý sau này.
Chỉnh lại
@OT trong code B nếu chạy trên máy mình sẽ không ra kết quả, không biết sao máy bạn lại chạy được
s = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & " ;Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
chỗ "Excel 12.0 Xml" chỉ đúng khi lấy dữ liệu file xlsx còn xlsm là Excel 12.0 macro hoặc Excel 12.0, xlsb là Excel 12.0
Code ABC kia chưa đúng vì khi max là ngày 99 thì Select Max(IIf(Mid(f1,7,2)=""99"",Mid(f1,1,6)&""00"",f1)) From [DATA$] sẽ ra ngày 00, lúc đó sẽ không tìm được record nào có ngày đó.
Cũng có thể do may mắn, máy mình thử chạy 3 lần không được, xóa chữ xml đi là được ngay. Tốt nhất cứ theo hướng dẫn [URL='www.connectionstrings.com/excel-2007/']ở đây thôi.
Mình cũng dùng 365, vừa thử khởi động lại máy thì thấy lại chạy được với Excel 12.0 xml. Chắc lúc trước máy mình có vấn đề.
Không biết ADO, viết bằng VBA được không?
Bạn tìm hiểu group by nhé. Mình khuyên là nên viết procedure ở phía server, code vba chi để truyền tham số và thực thi thôi.
vi du:
select mahang, sum(line_01)
from table
group by mahang
Vấn đề không hẳn là dữ liệu lớn vì dùng procedure chưa chắc nhanh hơn, mà quan trọng ở bảo mật, vì người dùng biết bạn đang truy vấn bảng nào, nếu người ta có quyền write thì người ta có thể làm nhiều việc xấu.
Còn query như sau:
SELECT MAHANG,TENHANG,CHUNGLOAI , sum(TONGCONG) AS TONGCONG
FROM TABLE
WHERE NGAY BETWEEN TU_NGAY AND DEN_NGAY
GROUP BY MAHANG,TENHANG,CHUNGLOAI
Bạn thử code sau nhé:
Sao không dùng OR anh ơi
Dựa vào file của chủ thớt rồi làm theo từng đoạn thôi bạn. Ý tưởng là thế, còn sử dụng phải tùy biến.
Em lặp lại việc gán câu lệnh SQL cho recordset mới trước khi đóng cn.
Có vẻ bạn cần tìm hiểu rõ SQL và ADO thêm chút là biến tấu được, khỏi nhờ diễn đàn chi cho vất vả
Đây là lý do trong mấy file làm demo lúc trước, anh luôn có hàm tạo kết nối (connection) riêng và hàm lấy Recordset riêng chứ không gộp chung vô cái hàm như của em hiện tại.
– Khi khởi chạy sẽ gọi hàm kết nối rồi để đó.
– Lấy recordset các kiểu, sau khi xong mới đóng kết nối.
Với hàm kết nối độc lập, trong vài trường hợp khi xử lý recordset cần ngắt kết nối tạm thời thì vẫn có thể chủ động ngắt rồi tạo lại sau khi xử lý xong Recordset, cập nhật về hệ thống.
Em dùng hàm Format, Code sau chưa đưa điều kiện lọc, em tự thêm vào nhé.
Em nên tạo các Store Procedure, View rồi sau đó gọi nó thôi.
Hiểu nôm na Store Procedure giống như 1 hàm, ví dụ như hàm trong Excel. Khi cần tìm hay lấy dữ liệu ra bảng khác thì bạn phải vào bảng gốc để tìm, lọc… rồi lấy kết quả đưa chỗ khác. Nhưng bạn dùng hàm thì không phải thao tác trực tiếp trên bảng gốc. Hàm sẽ lấy dữ liệu thảo điều kiện.
Quay lại Store Procedure hơn chỗ là nó có thể thực hiệc các lệnh thêm, sửa, xóa vào dữ liệu bảng gốc.
Nếu em có quyền trong SQL Server Management Stufio thì em vô folder Security -> Login -> Tạo user và thiết lập "User Mapping" tới cái Database mà em muốn chỉ cho dùng "SELECT.." là: db_datareader
Em tạo User Login rồi test xem User đó hoạt động như thế nào, không ảnh hưởng gì đâu. Tạo một Database tạm rồi thử nghiệm trên database đó thôi. Trong hình cái database "abc" là database tạm.2523252225212520
Em kiếm tài liệu đọc thêm nhe. Cái vụ phân quyền của SQL Server nó rộng lắm, anh không hướng dẫn nỗi đâu.. 🙂
Stored Procedure (1) chứ không phải Store Procedure (2).
(1) Tiếng Anh, trạng thái past participle được dùng cho tình huống thụ động (được/bị). Ở đây nói cái procedure (phương thức) được stored (lưu trữ/chứa) sẵn.
(2) cũng trong tiếng Anh, trường hợp 2 này thì Store là danh tự được dùng như tĩnh để bổ nghĩa cho danh tự đi tiếp theo. Và vì hai tự được hiểu theo danh cho nên từ thứ nhất là cửa hàng (kho), và từ thứ hai là quy trình. Dịch hai từ là quy trình cửa hàng.
Thao tác ngay trong SSMS, tạo New query rồi gõ câu lệnh nay vô:
Insert Into dbo.tblHangHoa (STT,MA_HANG,SOLUONG) Values (4,'MH0006',100)
Delete From dbo.tblHangHoa Where STT=3
Trời đất, STT (?)
Còn gì là CSDL LH nữa.
Lúc nãy không để ý vụ này :). Em OT xem lại cách thiết kế Table nhé, không cần mấy cột STT lãng phí này đâu.
Định nghĩa thế nào là một dòng?
Luật đáng ghi nhớ: khi viết câu string cho lệnh SQL, đừng bao giờ tiết kiệm số dấu cách.
Và do vậy:
Mẹo tốt để tránh lỗi khi viết một câu lệnh SQL: luôn luôn mở đầu chuỗi bằng dấu cách. Trừ phi chỗ đó là tham số.
mySQL = " select * from BC_TONG where C5 = '" & (Sheet6.Range("S2")) & "'" & _
" and C6 = '" & (Sheet6.Range("T2")) & "'" & _ (dấu cách thêm vào trước and, nhưng không trước dấu nháy ' , vì ' là một phần của tham số)
" and C7 = '" & (Sheet6.Range("U2")) & "'" & _
" and C8*1 = '" & (Sheet6.Range("V2") * 1) & "'" & _
" and C9 = '" & (Sheet6.Range("W2")) & "'" & _
" and C10 = '" & (Sheet6.Range("X2")) & "'" & _
" and C11 = '" & (Sheet6.Range("Y2")) & "' "
Tôi đã hứa với ban quản trị là tôi không phê phán các câu hỏi có từ viết tắt, nhưng tôi chưa hề nhượng bộ quyền từ chối không trả lới các câu hỏi ấy.
Dùng UNION ALL với điều kiện TYPE=2 sau đó gom nhóm lại là được nhé.
Em thử code sau nhé:
Nếu như tôi thì tôi làm báo cáo bằng CROSSTAB Query như hình sau:
2528
Bởi vì có thể trong cột TYPE có nhiều loại mà ta chưa biết nó là loại nào.
Do vậy anh mới nói phải dùng Crosstab Query như bài #144, em thử code như sau nhé:
Thêm cho em cái tiêu đề vào luôn nhé, bây giờ không cần quan tâm đến cột TYPE có bao nhiêu loại theo chuẩn.
CrossTab Query thường biến động số cột tuỳ theo dữ liệu (cụ thể là cột TYPE trong ví dụ này) do đó tôi thường đưa vô liệt kê đủ các cột TYPE vào câu lệnh SQL để cố định số cột TYPE, không trồi ra thụt vào :).
Tôi có thể dùng power pivot cho bài này không bạn!
Ah, tôi hiểu nhầm vấn đề, mà bạn connect với DB SQL Server hay Excel!
Tôi không có dữ liệu để test nên không biết chạy được không, nếu SQL thì tôi viết vầy (giả sử bạn có một bảng danh mục hàng )
Không cần bảng danh mục hàng được không bạn 🙂
Thường thì trong DB sẽ có bảng danh mục, muốn tạo riêng thì có thể tạo từ 2 bảng và
Thực ra vẫn còn một cách làm khác là join 2 bảng TDK và NX lại rồi pivot
Bạn copy 2 câu đó lại chạy chung là được, câu tạo Category chạy trước
Trong ADO hình như việc ghép 2 câu lệnh như vậy chạy không được , bạn có thể test thông qua connect SQL của excel được nó cho phép ghép 2 câu lệnh như vậy
Đây là trường hợp dùng pivot (tôi cũng chưa test chỉ viết trên word)
🙂 Anh góp ý vụ tính tồn kho này chút nhé. Vì xem mấy bài ở trên em đưa dữ liệu đã trích xuất ra theo từng mã hàng rồi nên cách xử lý sẽ khác. Thông thường cái tác vụ báo cáo NXT là: tính NXT của các mã hàng (hoặc 1 mã hàng) trong khoảng thời gian nào đó cần truy vấn. Do đó tốt nhất là em nên đưa cái CSDL để tính NXT có các thông tin: tất cả các mã hàng, ngày tháng nhập xuất, kho; Tồn đầu kỳ của tất cả các mã hàng – kho tồn – tháng/năm tồn (bảng TDK theo tháng phải khong em?). Khi đó câu lệnh truy vấn sẽ đầy đủ hơn, kết quả trả về cũng đáp ứng như cầu nhiều hơn.
Mỗi lần gửi thực thi SQL qua ADO trong Excel thì chỉ gửi 1 câu lệnh mà thôi
Ghép thì có UNION, JOIN… nhưng đó là ghép thành 1 lệnh
Muốn nhiều lệnh thì cần gửi thực thi nhiều lần (dùng chung 1 kết nối)
Bạn phải viết theo kiểu Excel, ví dụ
Chú ý lệnh:
sum(iif(isnull(b.),0,b.))
Không hiểu tại sao luôn 🙁
Bạn @VetMini giải thích dùm mình
Mình nghỉ nên có () mối liên kết sẽ tường minh hơn
Vậy bên bảng DMHH bảng cũng phải có kho luôn nhe bạn, tôi sửa lại trong môi trường SQL Server và khi DMHH có thêm cột kho
Còn connect qua SQL của Access bạn tùy biến lại
Chỗ trống như hình là "A" hay trống vậy em?
Em thử code sau và biến tấu nhé.
Bài toán này dùng Union là hợp lý, khó có thể dùng join. Vì sao thì đã giải thích ở bài trên.
Bạn gửi cho tôi câu lệnh bạn điều chỉnh tôi xem thử!
Lưu ý dùng join trong trường hợp này sẽ không chính xác, bởi vì mỗi dòng phát sinh sẽ có 1 cái tồn đầu kỳ tương ứng với số dòng.Bạn gắn thêm và thì bảng danh mục bảng phải có 2 cột đó và điều kiện join cũng phải dùng thêm 2 điều kiện này, sài join cũng bình thường thôi
Trong trường hợp này thì không phải là cái Table Dim Dmhh nữa mà là một Table Distinct mới tạo ra từ table TD và NX theo 3 điều kiện , và , bảng dmhh chỉ có sẽ không map được cả 3 điều kiện trên
Dùng Union chắc ổn hơn đấy bạn, còn dùng cách tôi bạn phải tạo thêm một table mới thay cho bảng DMHH , vì trong trường hợp này bảng DMHH không sử dụng được nữa, nếu dùng SQL server bạn có thể thử cách pivot
join nó giống hàm lookup trong excel cho phép tìm kiếm nhiều điều kiện
Thì tôi nói là bạn làm NXT theo 3 yếu tố ,, nên bảng DMHH sẽ không sử dụng được do nó chỉ có , nên bạn dùng cách union thì sẽ ổn hơn.
Còn vẫn muốn đi theo hướng đó thì bạn có thể thêm 1 đoạn tạo ra một bảng table DMHH mới như vầy, rồi chạy lại đoạn code trên (hoặc lồng vào đoạn code trên cũng được)
Trong SQLServer không có hàm IIF vì vậy em phải chuyển từ IIF sang Case When nhé.
Vẫn có hàm IIF nhe bạn
Em hỏi kỹ lại anh IT đó coi phiên bản 2012 có chưa nhé.
Ý anh là phiên bản 2012 về sau mới có hàm IIF. Những phiên bản trước đó chưa có hàm này. Hay ý em là khác? Ý em là em đang dùng SQLServer 2016 mà không dùng được đoạn truy vấn trên?
Em nên nghiên cứu thêm về các kiểu truy vấn nhé.
Chắc là
Mình thì nghĩ là A$ và B$ khác A và B nên Excel không hiểu, nếu không dùng name thì có thể đặt alias thành … FROM [A$] A INNER JOIN [B$] B… (mình đoán thôi).
Tôi thấy bạn sử dụng LIKE, nếu có nhiều nhóm như vậy bạn tạo thêm cột nhóm kho rồi dùng IN
2546
Giả sử bạn cần lấy các kho thuộc nhóm A,C thì bạn chỉnh điều kiện SQL như vầy, việc thêm cột có thể dùng Sub để tạo mà không cần thay đổi Table gốc
Nếu tài khoản của bạn của bạn chỉ được quyền Read thì việc tạo Table sẽ không được, nhưng Table tạm vẫn được, khi bạn không sử dụng SQL nữa Table đó sẽ tự xóa, tôi chỉnh lại code trên bằng việc sử dụng Table tạm
Việc sử dụng Subquery trong các môi trường khác không biết sao chứ trong SQL server bạn cứ sử dụng bình thường, trừ khi một sub được gọi nhiều hơn một lần thì nên lưu sub đó vào bảng tạm để tranh query nhiều lần
Thì tùy biến thôi bạn, nếu không thay đổi Table gốc thì dùng sub tạo thêm thôi, đây là ví dụ cho bài #218, bạn tùy biến cho trường hợp của bạn
Anh nghĩ em không nên quá lạm dụng dùng Subquerry. Có những bài toán dùng Subquery là tuyệt chiêu nhưng có những bài nó sẽ chạy ì ạch . Đối với CSDL lớn chục ngàn dòng, nhiều cột thì dùng nhiều cái subquery lồng nhau, sub của sub như bài của em sẽ không là cách hay. Thường thì nên tạo thêm table tạm để xử lý để khỏi phải lồng ghép nhiều query.
Em vào bài sau của anh @Nguyễn Duy Tuân sẽ có câu lệnh XNT em cần nhé.
http://www.giaiphapexcel.com/diendan/threads/thi-t%E1%BA%A1o-s%E1%BB%95-th-nxt-v%E1%BB%9Bi-t%E1%BB%91c-%C4%91%E1%BB%99-nhanh-nh%E1%BA%A5t-d%E1%BB%AF-li%E1%BB%87u-65-532-d%C3%B2ng.89723/