Những câu hỏi về "Viết một câu SQL" (1 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,695
Được thích
15,103
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ự)
 
Web KT

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

Back
Top Bottom