Những câu hỏi về "Viết một câu SQL" (2 người xem)

  • Thread starter Thread starter OverAC
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

OverAC

Đỗ Nguyên Bình
Thành viên BQT
Administrator
Tham gia
30/5/06
Bài viết
2,698
Được thích
15,152
Nhờ các anh chị viết giúp một câu SQL với tình trạng như sau:

Table1.Column1 có cấu trúc:
Mã:
'111122223333'
với 1111 là nhóm mã 1 (4 ký tự), 2222 nhóm mã 2 (4 ký tự), 3333 là nhóm mã 3 (4 ký tự)

Tôi muốn Select mid(Table1.column1, 1,4) nếu nó khác " " (4 ký tự trống) để lấy nhóm mã 1, nếu bằng " " (4 ký tự trống) thì select mid(table1.column1,9,4) để lấy 4 ký tự của nhóm mã 3

Nhờ các anh chị giúp đở

Thân cảm ơn.
OverAC
 
Nhờ các anh chị viết giúp một câu SQL với tình trạng như sau:

Table1.Column1 có cấu trúc:
Mã:
'111122223333'
với 1111 là nhóm mã 1 (4 ký tự), 2222 nhóm mã 2 (4 ký tự), 3333 là nhóm mã 3 (4 ký tự)

Tôi muốn Select mid(Table1.column1, 1,4) nếu nó khác " " (4 ký tự trống) để lấy nhóm mã 1, nếu bằng " " (4 ký tự trống) thì select mid(table1.column1,9,4) để lấy 4 ký tự của nhóm mã 3

Nhờ các anh chị giúp đở

Thân cảm ơn.
OverAC

Có phải ý Bình như hình bên dưới không?

39.jpg
 
Đúng rồi đó anh Đỏm ơi.

Viết ra sao đây anh? (không cho hiện column1 luôn, chỉ hiện column tach, trường hợp cả 2 nhóm 1111 và 3333 đều bằng " " (4 ký tự trống) thì không chọn)
 
Đúng rồi đó anh Đỏm ơi.

Viết ra sao đây anh? (không cho hiện column1 luôn, chỉ hiện column tach, trường hợp cả 2 nhóm 1111 và 3333 đều bằng " " (4 ký tự trống) thì không chọn)
Bình thử viết như sau:
-Thêm cái Format vào phòng hờ khi có 1 kí tự khác " ", nếu không muốn thì bỏ ra nhé:

Mã:
SELECT Format(IIf(Left([column1],4)<>" ",Left([column1],4),Right([column1],4)),"0000") AS Tach
FROM Table1;
 
Bình thử viết như sau:
-Thêm cái Format vào phòng hờ khi có 1 kí tự khác " ", nếu không muốn thì bỏ ra nhé:

Mã:
SELECT Format(IIf(Left([column1],4)<>" ",Left([column1],4),Right([column1],4)),"0000") AS Tach
FROM Table1;
Đây là cú pháp dùng cho Access, nếu là của T-SQL thì dùng cách này, T1 là tên bảng, F1 là tên trường của bảng, ColTemp là tên cột trả về
Mã:
SELECT    CASE 
            WHEN LEFT(F1,4)=REPLICATE(' ',4) THEN RIGHT(F1,4)
            ELSE LEFT(F1,4)
        END AS [ColTemp]
FROM T1
WHERE LEFT(F1,8) <> REPLICATE(' ',8)
 
Nhân tiện đây xin hỏi Bình luôn là chỉnh cái trường Column1 đó như thế nào mà khi gõ 4 khoảng trắng cuối cùng thì nó vẫn là 4 khoảng trắng, không bị mất đi 4 khoảng trắng cuối đó ?
Mình xin cám ơn
 
hi anh Đỏm, em mới bắt đầu viết SQL nên không rành IIF hay Format, tìm đọc sách thì thấy có format và hiểu còn IIF thì anh nói em mới biết

hi bác rollover79, em đang viết VBA rồi sẽ chuyển sang VB, không biết SQL Và T-SQL có gì khác nhau và vì sao nên dùng cái này mà không nên dùng cái kia?
 
Lần chỉnh sửa cuối:
.....đang viết VBA rồi sẽ chuyển sang VB, không biết SQL Và T-SQL có gì khác nhau và vì sao nên dùng cái này mà không nên dùng cái kia?
Hi Bình, T-SQL là Transact-SQL là công cụ trong Microsoft SQL-Server, có thể được phát biểu dưới hình thức 1 thủ tục (Procedure), 1 bảng động (View), để truy xuất dữ liệu, tạo một thủ tục xử lý dữ liệu, v.v...., hoặc dưới dạng bẫy lỗi (Trigger).
Còn SQL statement (được dùng trong Access, Excel,....) là công cụ để truy vấn/chỉnh sửa/thêm bớt dữ liệu (có khi gọi là SQL query) ở dạng cơ bản mà thôi.
Nếu mình làm việc nhiều trên SQL-Server và Cristal report sẽ thấy rõ sự khác biệt giữa T-SQL và SQL statement. T-SQL xử lý được nhiều thứ hơn, phát biểu đa dạng hơn.


Nhân tiện đây xin hỏi Bình luôn là chỉnh cái trường Column1 đó như thế nào mà khi gõ 4 khoảng trắng cuối cùng thì nó vẫn là 4 khoảng trắng, không bị mất đi 4 khoảng trắng cuối đó ?
Field đó cho nó thuộc tính Text hoặc Memo là được mà anh.
 
Lần chỉnh sửa cuối:
Field đó cho nó thuộc tính Text hoặc Memo là được mà anh.
Đưa nó về thuộc tính đó rồi thế nhưng không hiểu nó vẫn không chịu kiểu nhập liệu này, sau khi Enter nó sẽ cắt bỏ mấy cái khoản trắng đó.
VD: nhập "XXXXX_______X" Thì OK, nhưng nhập "XXXXXX______" thì nó tự động trả về "XXXXXX"
 
Select với 2 column ngày trong cùng 1 bảng cho ra 1 cột kết quả.

Hi các bác,

Em có một tình huống đặc biệt như sau:

Table1 ngày có 2 cột ngày là cột ngày nghi nhận nghiệp vụ và ngày chứng từ.
Ngày ghi nhận​
|
Số nghiệp vụ​
|
Ngày chứng từ​
|
Số chứng từ​
|
Số tiền​
|
9/13/2010​
|
1​
|
9/10/2010​
|
837​
|
10,425,000​
|
9/14/2010​
|
2​
|
9/10/2010​
|
633​
|
1,151,000​
|
9/15/2010​
|
3​
|
9/11/2010​
|
122​
|
7,500,000​
|
9/15/2010​
|
4​
|
9/12/2010​
|
272​
|
6,502,000​
|
9/16/2010​
|
5​
|
9/14/2010​
|
919​
|
3,433,000​
|
9/16/2010​
|
6​
|
9/13/2010​
|
368​
|
3,900,000​
|
9/17/2010​
|
7​
|
9/13/2010​
|
860​
|
5,990,000​
|
9/18/2010​
|
8​
|
9/15/2010​
|
146​
|
5,715,000​
|
9/18/2010​
|
9​
|
9/15/2010​
|
2​
|
5,189,000​
|
9/19/2010​
|
10​
|
9/16/2010​
|
755​
|
1,779,000​
|
9/19/2010​
|
11​
|
9/16/2010​
|
151​
|
5,204,000​
|
9/19/2010​
|
12​
|
9/17/2010​
|
422​
|
2,423,000​
|
9/20/2010​
|
13​
|
9/19/2010​
|
970​
|
9,631,000​
|
9/23/2010​
|
14​
|
9/22/2010​
|
735​
|
10,774,000​
|

Em muốn có một kết quả select như sau:
Ngày ghi nhận​
|
Số lượng nghiệp vụ​
|
Số chứng từ​
|
Tổng số tiền theo ngày nghiệp vụ​
|
Tổng số tiền theo ngày chứng từ​
|
=ngày được group unique date|=count of số nghiệp vụ theo ngày nghiệp vụ|=count of số lượng chứng từ phát sinh dựa theo ngày của chứng từ|=sum of số tiền theo ngày nghiệp vụ|=sum of số tiền theo ngày nghiệp vụ|
9/13/2010​
| | | | |
9/14/2010​
| | | | |
9/15/2010​
| | | | |
9/16/2010​
| | | | |
9/17/2010​
| | | | |
9/18/2010​
| | | | |
9/19/2010​
| | | | |
9/20/2010​
| | | | |
9/21/2010​
| | | | |
9/22/2010​
| | | | |
9/23/2010​
| | | | |

Không biết mình có thể làm được như vậy không và nếu được thì viết SQL như thế nào?

Thân cảm ơn
OverAC
 
Hi các bác,

Em có một tình huống đặc biệt như sau:

Table1 ngày có 2 cột ngày là cột ngày nghi nhận nghiệp vụ và ngày chứng từ.
Ngày ghi nhận​
|
Số nghiệp vụ​
|
Ngày chứng từ​
|
Số chứng từ​
|
Số tiền​
|
9/13/2010​
|
1​
|
9/10/2010​
|
837​
|
10,425,000​
|
9/14/2010​
|
2​
|
9/10/2010​
|
633​
|
1,151,000​
|
9/15/2010​
|
3​
|
9/11/2010​
|
122​
|
7,500,000​
|
9/15/2010​
|
4​
|
9/12/2010​
|
272​
|
6,502,000​
|
9/16/2010​
|
5​
|
9/14/2010​
|
919​
|
3,433,000​
|
9/16/2010​
|
6​
|
9/13/2010​
|
368​
|
3,900,000​
|
9/17/2010​
|
7​
|
9/13/2010​
|
860​
|
5,990,000​
|
9/18/2010​
|
8​
|
9/15/2010​
|
146​
|
5,715,000​
|
9/18/2010​
|
9​
|
9/15/2010​
|
2​
|
5,189,000​
|
9/19/2010​
|
10​
|
9/16/2010​
|
755​
|
1,779,000​
|
9/19/2010​
|
11​
|
9/16/2010​
|
151​
|
5,204,000​
|
9/19/2010​
|
12​
|
9/17/2010​
|
422​
|
2,423,000​
|
9/20/2010​
|
13​
|
9/19/2010​
|
970​
|
9,631,000​
|
9/23/2010​
|
14​
|
9/22/2010​
|
735​
|
10,774,000​
|

Em muốn có một kết quả select như sau:
Ngày ghi nhận​
|
Số lượng nghiệp vụ​
|
Số chứng từ​
|
Tổng số tiền theo ngày nghiệp vụ​
|
Tổng số tiền theo ngày chứng từ​
|
=ngày được group unique date|=count of số nghiệp vụ theo ngày nghiệp vụ|=count of số lượng chứng từ phát sinh dựa theo ngày của chứng từ|=sum of số tiền theo ngày nghiệp vụ|=sum of số tiền theo ngày nghiệp vụ|
9/13/2010​
| | | | |
9/14/2010​
| | | | |
9/15/2010​
| | | | |
9/16/2010​
| | | | |
9/17/2010​
| | | | |
9/18/2010​
| | | | |
9/19/2010​
| | | | |
9/20/2010​
| | | | |
9/21/2010​
| | | | |
9/22/2010​
| | | | |
9/23/2010​
| | | | |

Không biết mình có thể làm được như vậy không và nếu được thì viết SQL như thế nào?

Thân cảm ơn
OverAC
Khi đã Group theo thông tin nào thì dữ liệu phải được tính toán dựa trên thông tin đã được Group đó. Ở đây tôi thấy Group theo Ngày ghi nhận, nhưng dữ liệu có tính theo cả Ngày chứng từ thì có vẻ không hợp lý lắm. Để rõ hơn bạn có thể fill dữ liệu mong muốn từ dữ liệu mẫu vào mẫu kết quả xem sao.
 
Bình xem thử có phải từ dữ liệu như sheet data trong file, kết quả yêu cầu nằm ở sheet ketqua cũng trong file hay không?
 

File đính kèm

Hi anh Mỹ,

Hoàn toàn đúng như cách tính theo yêu cầu.
Em đã nghĩ phải tạo ra một table chỉ ghi ngày, sau đó right join với table1 cuối cùng sum, và count group by ngày của table ngày.

Không biết có phải như vậy không vì viết không rành, sai tùm lum không biết sai ở đâu?
 
Anh không biết viết SQL lồng, do đó tạo 2 query trung gian: 1 đếm và tính tổng theo ngày ghi nhận NV (Query1), 1 đếm và tính tổng theo ngày chứng từ (Query2).
Sau đó join 2 cái trung gian đó lại giữa 2 field ngày: All record from Query1 and only those record in Query2 where the joined fields are equal.
 

File đính kèm

Hi anh Mỹ,

Hoàn toàn đúng như cách tính theo yêu cầu.
Em đã nghĩ phải tạo ra một table chỉ ghi ngày, sau đó right join với table1 cuối cùng sum, và count group by ngày của table ngày.
Hi Bình, bài này không cần Join đâu, mà chỉ cần 1 câu query dùng Union sau đó mới Group by, đại khái như sau:

SELECT A.NgayGhi, SUM(A.SLCtuNgayGhi) AS SLCtuNgayGhi, SUM(A.SoTienNgayGhi) AS SoTienNgayGhi, SUM(A.SLCtuTheoCT) AS SLCtuTheoCT, SUM(A.SoTienNgayCT) AS SoTienNgayCT
FROM
(
SELECT Ctu.ngayghi AS NgayGhi, Count(Ctu.[soct]) AS SLCtuNgayGhi, Sum(Ctu.stien) AS SoTienNgayGhi, sum(0) AS SLCtuTheoCT, Sum(0) AS SoTienNgayCT
FROM Ctu
GROUP BY Ctu.ngayghi

Union all

SELECT Ctu.ngayct As NgayGhi, 0 AS SLCtuNgayGhi, sum(0) AS SoTienNgayGhi, count(Soct) AS SLCtuTheoCT, Sum(ctu.stien) AS SoTienNgayCT
FROM Ctu
GROUP BY Ctu.ngayct
) AS A
GROUP BY A.NgayGhi
HAVING SUM(A.SLCtuNgayGhi) >0
Mượn File anh Mỹ để Test chút nhé.
 

File đính kèm

Trong dữ liệu mẫu của OverAC và 2 file của Cadi và ptm tôi thấy kết quả chỉ ra dữ liệu của Ngày Ghi nhận mà không ra dữ liệu của Ngày Chứng từ, ví dụ những Ngày Chứng từ là 10/9, 11/9, 12/9 thì không thấy có trong kết quả, không rõ nó có nghiệp vụ đặc thù gì chỗ này không vì tôi thấy kết quả thống kê ra có dữ liệu Số Chứng từ của ngày chứng từ và Tổng số tiền của ngày chứng từ. Theo tôi thì lẽ ra nó phải có cả những ngày này. Tôi xin gửi cả 2 phương pháp có những ngày này và không có ngày này như sau
1. Không có những ngày này
Mã:
SELECT DISTINCT T1.NgayGhi AS Ngay, 
    (SELECT COUNT(*) FROM Ctu T2 WHERE T2.NgayGhi=T1.NgayGhi) AS SLCtuNgayGhi, 
    (SELECT SUM(STien) FROM Ctu T2 WHERE T2.NgayGhi=T1.NgayGhi) AS SoTienNgayGhi, 
    (SELECT COUNT(*) FROM Ctu T2 WHERE T2.NgayCT=T1.NgayGhi) AS SLCtuNgayCT, 
    (SELECT SUM(STien) FROM Ctu T2 WHERE T2.NgayCT=T1.NgayGhi) AS SoTienNgayCT
FROM Ctu AS T1
2. Có cả những ngày này
Mã:
SELECT T1.Ngay, 
    (SELECT COUNT(*) FROM Ctu T2 WHERE T2.NgayGhi=T1.Ngay) AS SLCtuNgayGhi, 
    (SELECT SUM(STien) FROM Ctu T2 WHERE T2.NgayGhi=T1.Ngay) AS SoTienNgayGhi, 
    (SELECT COUNT(*) FROM Ctu T2 WHERE T2.NgayCT=T1.Ngay) AS SLCtuNgayCT, 
    (SELECT SUM(STien) FROM Ctu T2 WHERE T2.NgayCT=T1.Ngay) AS SoTienNgayCT
FROM (
    SELECT  NgayGhi as[Ngay]
    FROM Ctu 
    UNION
    SELECT NgayCT 
    FROM Ctu
) AS T1;
 

File đính kèm

Trong dữ liệu mẫu của OverAC và 2 file của Cadi và ptm tôi thấy kết quả chỉ ra dữ liệu của Ngày Ghi nhận mà không ra dữ liệu của Ngày Chứng từ, ví dụ những Ngày Chứng từ là 10/9, 11/9, 12/9 thì không thấy có trong kết quả, không rõ nó có nghiệp vụ đặc thù gì chỗ này không vì tôi thấy kết quả thống kê ra có dữ liệu Số Chứng từ của ngày chứng từ và Tổng số tiền của ngày chứng từ. Theo tôi thì lẽ ra nó phải có cả những ngày này. Tôi xin gửi cả 2 phương pháp có những ngày này và không có ngày này như sau

Trong trường hợp này, anh có thể bỏ qua phần "HAVING SUM(A.SLCtuNgayGhi) >0" trong đoạn query của em bên dưới là được.
 
hi bác rollover

Vậy là vấn đề đã đuợc giải quyết, cảm ơn các bác nhưng bác cho hỏi trong câu này có T2 và Ctu T2, sao mình phải cần cái này
Mã:
SELECT T1.Ngay, (SELECT COUNT(*) FROM Ctu T2 WHERE T2.NgayGhi=T1.Ngay) AS SLCtuNgayGhi, (SELECT SUM(STien) FROM Ctu T2 WHERE T2.NgayGhi=T1.Ngay) AS SoTienNgayGhi, (SELECT COUNT(*) FROM Ctu T2 WHERE T2.NgayCT=T1.Ngay) AS SLCtuNgayCT, (SELECT SUM(STien) FROM Ctu T2 WHERE T2.NgayCT=T1.Ngay) AS SoTienNgayCT
FROM [SELECT  NgayGhi as[Ngay]
    FROM Ctu 
    UNION
    SELECT NgayCT 
    FROM Ctu
]. AS T1;
Em sửa lại thành thì không chạy được?
Mã:
SELECT T1.Ngay, (SELECT COUNT(*) FROM Ctu WHERE Ctu.NgayGhi=T1.Ngay) AS SLCtuNgayGhi, (SELECT SUM(STien) FROM Ctu WHERE Ctu.NgayGhi=T1.Ngay) AS SoTienNgayGhi, (SELECT COUNT(*) FROM Ctu WHERE ctu.NgayCT=T1.Ngay) AS SLCtuNgayCT, (SELECT SUM(STien) FROM Ctu  WHERE ctu.NgayCT=T1.Ngay) AS SoTienNgayCT
FROM [SELECT  NgayGhi as[Ngay]
    FROM Ctu 
    UNION
    SELECT NgayCT 
    FROM Ctu
]. AS T1;
 
hi bác rollover

Vậy là vấn đề đã đuợc giải quyết, cảm ơn các bác nhưng bác cho hỏi trong câu này có T2 và Ctu T2, sao mình phải cần cái này
Mã:
SELECT T1.Ngay, (SELECT COUNT(*) FROM Ctu T2 WHERE T2.NgayGhi=T1.Ngay) AS SLCtuNgayGhi, (SELECT SUM(STien) FROM Ctu T2 WHERE T2.NgayGhi=T1.Ngay) AS SoTienNgayGhi, (SELECT COUNT(*) FROM Ctu T2 WHERE T2.NgayCT=T1.Ngay) AS SLCtuNgayCT, (SELECT SUM(STien) FROM Ctu T2 WHERE T2.NgayCT=T1.Ngay) AS SoTienNgayCT
FROM [SELECT  NgayGhi as[Ngay]
    FROM Ctu 
    UNION
    SELECT NgayCT 
    FROM Ctu
]. AS T1;
Em sửa lại thành thì không chạy được?
Mã:
SELECT T1.Ngay, (SELECT COUNT(*) FROM Ctu WHERE Ctu.NgayGhi=T1.Ngay) AS SLCtuNgayGhi, (SELECT SUM(STien) FROM Ctu WHERE Ctu.NgayGhi=T1.Ngay) AS SoTienNgayGhi, (SELECT COUNT(*) FROM Ctu WHERE ctu.NgayCT=T1.Ngay) AS SLCtuNgayCT, (SELECT SUM(STien) FROM Ctu  WHERE ctu.NgayCT=T1.Ngay) AS SoTienNgayCT
FROM [SELECT  NgayGhi as[Ngay]
    FROM Ctu 
    UNION
    SELECT NgayCT 
    FROM Ctu
]. AS T1;
Được chứ, cái T2 đơn giản nó chỉ là ALIAS của cái bảng trong câu Sub Query thôi, dùng ALIAS như vậy dễ phân biệt được bảng bên trong và bảng bên ngoài hơn thôi.
 
Nhưng đoạn sau chạy báo lỗi : Invalid bracketing of name 'SELECT ngayghi as[ngay'
(lỗi được trích đã được kiểm tra và không sai lệch dù chỉ là một kí tự)
 
Nhưng đoạn sau chạy báo lỗi : Invalid bracketing of name 'SELECT ngayghi as[ngay'
(lỗi được trích đã được kiểm tra và không sai lệch dù chỉ là một kí tự)
Lỗi này là do khi lưu câu query lại khi mở ra editor của access tự chuyển dấu () thành [], bạn xem lại hoặc có thể copy lại câu query tôi gửi trong bài #16 xem. Hoặc ngoài các cập dấu [] để bao tên trường, bạn thay hết thành cặp (), trước chứ AS T1 cũng bị thừa dấu ., bạn xóa cả dấu . này đi.
 
Tính số nhân viên đi công tác từ ngày tới ngày

Hi các bác,
Lại tiếp tục có một bài toán SQL nhờ các bác giúp

Dữ liệu nguồn, với nhân viên có đoạn từ ngày đi và ngày về. yêu cầu tính ra trong 1 ngày có bao nhiêu nhân viên đi công tác.

Dữ liệu:
MaNhanVien​
|
NgayDi​
|
NgayVe​
|
19​
|
1/21/2009​
|
1/23/2009​
|
15​
|
1/7/2009​
|
1/10/2009​
|
48​
|
1/11/2009​
|
1/15/2009​
|
40​
|
1/21/2009​
|
1/25/2009​
|
38​
|
1/6/2009​
|
1/9/2009​
|
30​
|
1/25/2009​
|
2/1/2009​
|
9​
|
1/4/2009​
|
1/14/2009​
|
89​
|
1/19/2009​
|
1/25/2009​
|
80​
|
1/14/2009​
|
1/22/2009​
|
61​
|
1/3/2009​
|
1/5/2009​
|
83​
|
1/14/2009​
|
1/16/2009​
|
39​
|
1/10/2009​
|
1/20/2009​
|
30​
|
1/16/2009​
|
1/18/2009​
|
29​
|
1/25/2009​
|
1/26/2009​
|
58​
|
1/26/2009​
|
2/2/2009​
|
72​
|
1/18/2009​
|
1/20/2009​
|

Kết quả
Ngay​
|
SoNhanVienĐiCongTac​
|
1/3/2009​
|
1​
|
1/4/2009​
|
2​
|
1/5/2009​
|
2​
|
1/6/2009​
|
2​
|
1/7/2009​
|
3​
|
1/8/2009​
|
3​
|
1/9/2009​
|
3​
|
1/10/2009​
|
3​
|
1/11/2009​
|
3​
|
1/12/2009​
|
3​
|
1/13/2009​
|
3​
|
1/14/2009​
|
5​
|
1/15/2009​
|
4​
|
....|...|
 

File đính kèm

Dữ liệu nguồn, với nhân viên có đoạn từ ngày đi và ngày về. yêu cầu tính ra trong 1 ngày có bao nhiêu nhân viên đi công tác.
Dữ liệu:
Theo mình bài toán này chắc là không dùng quẻy thông thường rồi mà phải là bài toán vòng lặp.
Các thao tác mở new table, new recordset và add field ... hiện tại chưa biết gì hết.
Bài này nếu làm = excel thì mình sẽ làm như sau.
Hy vọng Access cũng tựa như excel.
Nhờ các Bạn hướng dẫn để mình học hỏi thêm. Cám ơn!

Google mới tìm ra 1 cách = ADO về addrecord. (code đăng trên PC world). Nhưng có lúc OK và có lúc báo lỗi về connection.
Mình giả lập ngày đầu và ngày cuối cho nhanh, nếu có thể thì duyệt qua Data 1 lần để lấy ngày.
Do mày mò nên code dài quá và thấy thế nào.
PHP:
Option Compare Database
'Khai bao cac bien can dung
 'Dim Connection As ADODB.Connection
 Dim Connection As Object
 Dim Command As ADODB.Command
 Dim RecordSet1 As ADODB.Recordset
 Dim RecordSet2 As ADODB.Recordset
 Dim iNgay As Long, iNgayDi As Long, iNgayVe As Long
 Dim fDate As Date, eDate As Date, i As Long, s As Long, SL As Long
Private Sub TinhToan()
  'Khai bao cac bien can dung'
  Dim strSQL As String
  Dim MyConString As String
  MyConString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source = E:\Tam\OverAc\OverOne.mdb"
  'Tao connection toi database'
  Set Connection = New ADODB.Connection
  Connection.Open MyConString
  'Tao command làm viec voi database'
  Set Command = New ADODB.Command
  Command.ActiveConnection = Connection
  'Xoa table Ketqua if true
  Command.CommandText = "drop table KetQua"
  On Error Resume Next
  Command.Execute
  'Xay dung SQL tao moi table KetQua gom co 2 field Ngay va soluong'
   strSQL = "CREATE TABLE KetQua (Ngay date, Soluong integer)"
  'Tao table KetQua'
  Command.CommandText = strSQL
  Command.Execute
  'Tao recordset chua các data cua table Data'
  Set RecordSet1 = New ADODB.Recordset
  RecordSet1.Open "Data", Connection, adOpenStatic, adLockReadOnly, adCmdTable
  'Tao recordset quan ly du lieu cua table KetQua'
  Set RecordSet2 = New ADODB.Recordset
  RecordSet2.Open "KetQua", Connection, adOpenKeyset, adLockOptimistic, adCmdTable
  fDate = "03/01/2009"
  eDate = "02/02/2009"
  'Tao tung record cua table KetQua'
  For i = CLng(fDate) To CLng(eDate)
    iNgay = i
    SL = 0
    'Add ngay vao'
    With RecordSet2
      .AddNew
      .Fields("Ngay").Value = CDate(iNgay)
    End With
    With RecordSet1
      While Not .EOF
        iNgayDi = CLng(.Fields("NgayDi").Value)
        iNgayVe = CLng(.Fields("NgayVe").Value)
        If iNgay >= iNgayDi Then
          If iNgay <= iNgayVe Then
            SL = SL + 1
          End If
        End If
        'di chuyen den record ke'
        .MoveNext
      Wend
      'di chuyen den record dau'
      .MoveFirst
    End With
    RecordSet2.Fields("SoLuong").Value = SL
    RecordSet2.Update
  Next i
  RecordSet1.Close:  RecordSet2.Close:  Connection.Close
  Set Connection = Nothing: Set Command = Nothing
End Sub
 

File đính kèm

Lần chỉnh sửa cuối:
Theo mình bài toán này chắc là không dùng quẻy thông thường rồi mà phải là bài toán vòng lặp.
Các thao tác mở new table, new recordset và add field ... hiện tại chưa biết gì hết.
Bài này nếu làm = excel thì mình sẽ làm như sau.
Hy vọng Access cũng tựa như excel.
Nhờ các Bạn hướng dẫn để mình học hỏi thêm. Cám ơn!
Code của ThuNghi cũng tốt nhưng bị lệ thuộc vào Excel nhiều quá (Range, WorksheetFunction...)
Tôi thì làm vầy:
PHP:
Function GetWd(sDay, eDay)
  Dim i As Long, j As Long, nD As Long, k As Long
  Dim Dic1, Dic2, Arr(), sTmp, eTmp
  On Error Resume Next
  sTmp = sDay: eTmp = eDay
  Set Dic1 = CreateObject("Scripting.Dictionary")
  Set Dic2 = CreateObject("Scripting.Dictionary")
  For i = LBound(sTmp, 1) To UBound(sTmp, 1)
    For j = LBound(sTmp, 2) To UBound(sTmp, 2)
      If sTmp(i, j) <> "" Then
        For nD = sTmp(i, j) To eTmp(i, j)
          If Not Dic1.Exists(nD) Then
            k = k + 1
            Dic1.Add nD, 1: Dic2.Add nD, k
            ReDim Preserve Arr(1 To 2, 1 To k)
            Arr(1, k) = nD: Arr(2, k) = 1
          Else
            Dic1.Item(nD) = Dic1.Item(nD) + 1
            Arr(2, Dic2.Item(nD)) = Dic1.Item(nD)
          End If
        Next
      End If
    Next
  Next
  GetWd = Arr
End Function
Code này không sử dụng bất cứ thứ gì của Excel nên tôi nghĩ có thể áp dụng vào những ứng dụng khác
Trên Excel, để áp dụng hàm này, tôi sẽ viết thêm 1 code nữa như sau:
PHP:
Sub Main()
  Dim sDay, eDay, res
  sDay = Sheet2.Range("B2:B17")
  eDay = Sheet2.Range("C2:C17")
  res = GetWd(sDay, eDay)
  Range("E2:F2").Resize(UBound(res, 2)) = WorksheetFunction.Transpose(res)
End Sub
 

File đính kèm

Mày mò làm lại cái code theo hướng Arr, nhưng còn vướng mắc ở lấy tên file hiện hành.
Chưa biết cách lấy theo như excel. vướng ở chỗ này.
PHP:
Sub ganStr()
 fName = "E:\Tam\OverAc\OverTwo"
 MyConString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source =" & fName & ".mdb"
End Sub


Các bạn chỉ giúp cách lấy tên, Path ... của file mà nó chứa code.
Xin cám ơn.
PHP:
Option Compare Database
'Khai bao cac bien can dung
 Dim Connection As Object
 Dim Command As ADODB.Command
 Dim RecordSet1 As ADODB.Recordset
 Dim RecordSet2 As ADODB.Recordset
 Dim iNgay As Long, iNgayDi As Long, iNgayVe As Long
 Dim fDate As Date, eDate As Date, i As Long, j As Long, SL As Long
 Dim strSQL As String, MyConString As String, fName As String
  Dim Arr(), soRec As Long, soField As Long
Sub KetNoi()
Set Connection = New ADODB.Connection
Connection.Open MyConString
'Tao command làm viec voi database
Set Command = New ADODB.Command
Command.ActiveConnection = Connection
Set RecordSet1 = New ADODB.Recordset: Set RecordSet2 = New ADODB.Recordset
End Sub
Sub BoKetNoi()
 Connection.Close: Set RecordSet1 = Nothing: Set RecordSet2 = Nothing
 Set Connection = Nothing: Set Command = Nothing
End Sub
Sub ganStr()
 fName = "E:\Tam\OverAc\OverTwo"
 MyConString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source =" & fName & ".mdb"
End Sub
Private Sub TaoKQ()
  ganStr
  KetNoi
  'Tao recordset chua các data cua table Data
  RecordSet1.Open "Data", Connection, adOpenStatic, adLockReadOnly, adCmdTable
  With RecordSet1
    soRec = .RecordCount
    soField = .Fields.Count
  End With
  ReDim Arr(1 To soRec, 1 To soField)
  fDate = 0
  With RecordSet1
   While Not .EOF
    For i = 1 To soRec
      Arr(i, 1) = .Fields("NgayDi").Value
      Arr(i, 2) = .Fields("NgayVe").Value
      If fDate = 0 Or CLng(fDate) > CLng(Arr(i, 1)) Then fDate = Arr(i, 1)
      If eDate < Arr(i, 2) Then eDate = Arr(i, 2)
      .MoveNext
     Next i
   Wend
  End With
  TaoMDB
  'Mo Recordset2
  RecordSet2.Open "KetQua", Connection, adOpenKeyset, adLockOptimistic, adCmdTable
   'Tao tung record cua table KetQua
  For i = CLng(fDate) To CLng(eDate)
    iNgay = i
    SL = 0
    For j = 1 To UBound(Arr)
     If iNgay >= Arr(j, 1) Then
       If iNgay <= Arr(j, 2) Then
         SL = SL + 1
       End If
     End If
    Next j
    With RecordSet2
     .AddNew
     .Fields("Ngay").Value = CDate(iNgay)
     .Fields("SoLuong").Value = SL
     .Update
    End With
  Next i
  BoKetNoi
  Erase Arr
End Sub
Sub TaoMDB()
'Xoa va tao table Ketqua if true
Command.CommandText = "drop table KetQua"
On Error Resume Next
Command.Execute
'Xay dung SQL tao moi table KetQua gom co 2 field Ngay va soluong
 strSQL = "CREATE TABLE KetQua (Ngay date, Soluong integer)"
'Tao table KetQua
Command.CommandText = strSQL
Command.Execute
End Sub
Chưa biết cách gì lấy dữ liệu ở table ngoài cách ADO.
 
Dữ liệu nguồn, với nhân viên có đoạn từ ngày đi và ngày về. yêu cầu tính ra trong 1 ngày có bao nhiêu nhân viên đi công tác.
Bài này giải quyết đơn giản nếu có thêm 1 bảng có 1 field duy nhất có các record chạy từ 1 đến 31. Bình thử xem.
 
Bài này giải quyết đơn giản nếu có thêm 1 bảng có 1 field duy nhất có các record chạy từ 1 đến 31. Bình thử xem.
Giả dụ có 1 table như vậy thì Kiệt sẽ làm thế nào.
Liệu có thể dùng query giải quyết vấn đề trên.
Rất mong các bạn cho ý kiến.
Xin cám ơn.
 
Giả dụ có 1 table như vậy thì Kiệt sẽ làm thế nào.
Liệu có thể dùng query giải quyết vấn đề trên.
Rất mong các bạn cho ý kiến.
Xin cám ơn.
Nếu có bảng như vậy thì hoàn toàn giải quyết bằng query được bác ạ.
@Cadi: Chỉ giải quyết được bài toán cụ thể là dữ liệu Từ ngày nhỏ nhất và Đến ngày lớn nhất không vượt quá 31 thôi. Còn bài toán tổng quát Từ ngày bất kỳ tới Đến ngày bất kỳ thì không thể giải quyết được.
 
Nếu có bảng như vậy thì hoàn toàn giải quyết bằng query được bác ạ.
@Cadi: Chỉ giải quyết được bài toán cụ thể là dữ liệu Từ ngày nhỏ nhất và Đến ngày lớn nhất không vượt quá 31 thôi. Còn bài toán tổng quát Từ ngày bất kỳ tới Đến ngày bất kỳ thì không thể giải quyết được.
Trong acc có thể tạo 1 query tạo 1 table có ngày là fDate (cho trước) đến eDate (cho trước), mỗi ngày 1 record?
fDate="03/01/2009": eDate="02/02/2009"
RollOver hướng dẫn mình với.
Và bạn HD mình cách lấy tên file hiện hành trong ACC nhé.
Cám ơn.

Và bạn HD mình cách lấy tên file hiện hành trong ACC nhé.
Mới hỏi Bác Mỹ và có cách rồi
Nhưng nếu tham chiếu tới Acc thì
Extended Properties=Excel 8.0
Excel 8.0 phải thay là gì
 
Lần chỉnh sửa cuối:
Trong acc có thể tạo 1 query tạo 1 table có ngày là fDate (cho trước) đến eDate (cho trước), mỗi ngày 1 record?
fDate="03/01/2009": eDate="02/02/2009"
RollOver hướng dẫn mình với.
Và bạn HD mình cách lấy tên file hiện hành trong ACC nhé.
Cám ơn.


Mới hỏi Bác Mỹ và có cách rồi

Nhưng nếu tham chiếu tới Acc thì

Excel 8.0 phải thay là gì


ThuNghi tham khảo ở đây nhé

http://www.giaiphapexcel.com/forum/showthread.php?28120-ADODB-v%C3%A0-vi%E1%BB%87c-k%E1%BA%BFt-n%E1%BB%91i-Excel-v%C3%A0-Access-trong-c%C3%B4ng-t%C3%A1c-k%E1%BA%BF-to%C3%A1nn

Nếu từ Excel gọi file Acc thì : FName = ThisWorkbook.Path & "Database.mdb"
Nếu từ Acc gọi file Acc khác thì : FName = CurrentProject.Path & "Database.mdb"
 
Lần chỉnh sửa cuối:

Bài viết mới nhất

Back
Top Bottom