Truy vấn trong SQL?

Liên hệ QC
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.
Xin chào quanluu1989
Cảm ơn Bạn đã góp ý, phần mềm này của công ty OT cũng đang trong quá trình vừa thiết kế vừa sử dụng ạ, nên cũng có thể sẽ khó tránh khỏi lỗi thiết kế ạ.
 
Ví dụ dữ liệu chỉ tới tháng 2 năm 2020, ngày cuối sẽ là ngày nào?
Hic,con cũng không biết Bác ạ, nó còn tùy thuộc vào ngày mọi người thực hiện kiểm kê Bác ạ, thông thường là ngày cuối tháng cũng có thể là trước đó. Nếu chỉ có đến tháng 2 - loại bỏ ngày xx99 lấy ngày lớn nhất trong tháng 2 nếu không có thì mới lấy ngày 99 trong tháng 2 Bác ạ.
 
Hic,con cũng không biết Bác ạ, nó còn tùy thuộc vào ngày mọi người thực hiện kiểm kê Bác ạ, thông thường là ngày cuối tháng cũng có thể là trước đó. Nếu chỉ có đến tháng 2 - loại bỏ ngày xx99 lấy ngày lớn nhất trong tháng 2 nếu không có thì mới lấy ngày 99 trong tháng 2 Bác ạ.
Rắc rối rồi, SQL bài trước phải viết lại
 
Nếu lấy năm và tháng lớn nhất, trường hợp trong tháng đó chỉ có ngày 99 thì lấy ngày đó nếu có cả ngày khác trong tháng thì lấy max của ngày khác, câu truy vấn có thể dùng:
Mã:
SELECT *
FROM DATA
WHERE  date= (SELECT IIF(RIGHT(a,2)="00",a+99,a)
              FROM (SELECT MAX(IIF(RIGHT(date,2)="99",date-99,date)) AS a
                     FROM DATA));
Mục đích biến các ngày dạng yyyymm99 thành yyyymm00 để tìm max, tìm được max rồi nếu là ngày tháng bình thường thì giữ nguyên không thì chuyển lại về dạng yyyymm99.
 
Hic,dạ vâng có thể trong trường hợp dữ liệu con đưa lên là đúng nhưng trường hợp như Bác đang đề cập là gặp vấn đề ạ.
Nếu vậy thì câu lệnh SQL phải sửa lại sao vậy Bác.
Thử code
Mã:
Sub ABC()
  Dim cn As Object, rs As Object, SQL As String

  Set cn = CreateObject("ADODB.Connection")
  cn.Open ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=No""")
  SQL = "Select * From [DATA$] Where f1 = (Select Max(IIf(Mid(f1,7,2)=99,Mid(f1,1,6)&""00"",f1)) From [DATA$])"
  Set rs = cn.Execute(SQL)
  If Not rs.EOF() Then
    Sheets("sheet1").Range("A2").CopyFromRecordset rs
  End If
  rs.Close:    Set rs = Nothing
  cn.Close:    Set cn = Nothing
End Sub
 
Thử code
Mã:
Sub ABC()
  Dim cn As Object, rs As Object, SQL As String

  Set cn = CreateObject("ADODB.Connection")
  cn.Open ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=No""")
  SQL = "Select * From [DATA$] Where f1 = (Select Max(IIf(Mid(f1,7,2)=99,Mid(f1,1,6)&""00"",f1)) From [DATA$])"
  Set rs = cn.Execute(SQL)
  If Not rs.EOF() Then
    Sheets("sheet1").Range("A2").CopyFromRecordset rs
  End If
  rs.Close:    Set rs = Nothing
  cn.Close:    Set cn = Nothing
End Sub
Nếu lấy năm và tháng lớn nhất, trường hợp trong tháng đó chỉ có ngày 99 thì lấy ngày đó nếu có cả ngày khác trong tháng thì lấy max của ngày khác, câu truy vấn có thể dùng:
Mã:
SELECT *
FROM DATA
WHERE  date= (SELECT IIF(RIGHT(a,2)="00",a+99,a)
              FROM (SELECT MAX(IIF(RIGHT(date,2)="99",date-99,date)) AS a
                     FROM DATA));
Mục đích biến các ngày dạng yyyymm99 thành yyyymm00 để tìm max, tìm được max rồi nếu là ngày tháng bình thường thì giữ nguyên không thì chuyển lại về dạng yyyymm99.

Cảm ơn Bác HieuCD và Bạn Hau151978 nhiều ạ, đã cho OT 2 cách làm trên Excel và trong SQL.
Ngày mai đến cơ quan OT sẽ giả lập tình huống lỗi như đã đề cập để test thử ạ, nếu có vấn đề gì OT sẽ thông tin lại ở đây ạ.
Chúc mọi người nhiều sức khỏe, thân nhiện luôn luôn nằm trong tiêu chuẩn trong mùa chống dịch này ạ.
 
Cảm ơn Bác HieuCD và Bạn Hau151978 nhiều ạ, đã cho OT 2 cách làm trên Excel và trong SQL.
Ngày mai đến cơ quan OT sẽ giả lập tình huống lỗi như đã đề cập để test thử ạ, nếu có vấn đề gì OT sẽ thông tin lại ở đây ạ.
Chúc mọi người nhiều sức khỏe, thân nhiện luôn luôn nằm trong tiêu chuẩn trong mùa chống dịch này ạ.

Xin chào Bác HieuCD và Bạn Hau151978
OT thử tạo tình huống lỗi sảy ra,sửa ô A28205:
20200331 thành 20200499
Thì dữ liệu lọc sang sheets("KQ")
Code cho sub B ok, cho sub ABC chưa được ạ.
Mã:
Sub B()
    'Hau151978
    Dim cnn As New ADODB.Connection
    Dim rs As New ADODB.Recordset
    Dim s As String
    s = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & " ;Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
    cnn.Open s
    s = "SELECT * FROM [DATA$] " & _
        "WHERE DATE = (SELECT IIF(RIGHT(a,2)=""00"",a+99,a) " & _
        "FROM (SELECT MAX(IIF(RIGHT(DATE,2)=""99"",DATE-99,DATE)) AS a " & _
        "FROM [DATA$]));"

    rs.Open s, cnn
    Sheets("KQ").Range("A2:K10000").ClearContents
    Sheets("KQ").Range("A2").CopyFromRecordset rs
    rs.Close
    Set rs = Nothing
    cnn.Close
    Set cnn = Nothing
End Sub


Sub ABC()

    'HieuCD
    Dim cn As Object, rs As Object, SQL As String

    Set cn = CreateObject("ADODB.Connection")
    cn.Open ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=No""")
    SQL = "Select * From [DATA$] Where f1 = (Select Max(IIf(Mid(f1,7,2)=99,Mid(f1,1,6)&""00"",f1)) From [DATA$])"
    
    Set rs = cn.Execute(SQL)
    Sheets("KQ").Range("A2:K10000").ClearContents
    If Not rs.EOF() Then
        
        Sheets("KQ").Range("A2").CopyFromRecordset rs
    End If
    
    rs.Close:    Set rs = Nothing
    cn.Close:    Set cn = Nothing
    
End Sub
 

File đính kèm

  • SQL_MAX_DAY.xlsm
    833.2 KB · Đọc: 11
@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 đó.
 
Lần chỉnh sửa cuố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

Xin chào Hau151978,
Khi đọc thông tin trên của Bạn , OT thấy trong cùng thư mục xlsm vẫn còn tập tin xlsx , OT thử xóa xlsx đi thậm trí di truyển tập tin xlsm sang một thư mục mới và chạy sub B vẫn có kết quả.
OT không hiểu ADO sau khi chạy lần đầu tiên nó có lưu dữ liệu đâu không nữa T_T
Untitled.jpg
 
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 ở đây thôi.
 
Xin chào Bác HieuCD và Bạn Hau151978
OT thử tạo tình huống lỗi sảy ra,sửa ô A28205:
20200331 thành 20200499
Thì dữ liệu lọc sang sheets("KQ")
Code cho sub B ok, cho sub ABC chưa được ạ.
Mã:
Sub B()
    'Hau151978
    Dim cnn As New ADODB.Connection
    Dim rs As New ADODB.Recordset
    Dim s As String
    s = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & " ;Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
    cnn.Open s
    s = "SELECT * FROM [DATA$] " & _
        "WHERE DATE = (SELECT IIF(RIGHT(a,2)=""00"",a+99,a) " & _
        "FROM (SELECT MAX(IIF(RIGHT(DATE,2)=""99"",DATE-99,DATE)) AS a " & _
        "FROM [DATA$]));"

    rs.Open s, cnn
    Sheets("KQ").Range("A2:K10000").ClearContents
    Sheets("KQ").Range("A2").CopyFromRecordset rs
    rs.Close
    Set rs = Nothing
    cnn.Close
    Set cnn = Nothing
End Sub


Sub ABC()

    'HieuCD
    Dim cn As Object, rs As Object, SQL As String

    Set cn = CreateObject("ADODB.Connection")
    cn.Open ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=No""")
    SQL = "Select * From [DATA$] Where f1 = (Select Max(IIf(Mid(f1,7,2)=99,Mid(f1,1,6)&""00"",f1)) From [DATA$])"
   
    Set rs = cn.Execute(SQL)
    Sheets("KQ").Range("A2:K10000").ClearContents
    If Not rs.EOF() Then
       
        Sheets("KQ").Range("A2").CopyFromRecordset rs
    End If
   
    rs.Close:    Set rs = Nothing
    cn.Close:    Set cn = Nothing
   
End Sub
Chỉnh lại
Mã:
Sub ABC()
  Dim cn As Object, rs As Object, SQL As String

  Set cn = CreateObject("ADODB.Connection")
  cn.Open ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=no""")
  SQL = "Select * From [DATA$] Where IIf(Mid(f1,7,2)=99,Mid(f1,1,6)&""00"",f1) = (Select Max(IIf(Mid(f1,7,2)=99,Mid(f1,1,6)&""00"",f1)) From [DATA$])"
  Set rs = cn.Execute(SQL)
  If Not rs.EOF() Then
    Sheets("sheet1").Range("A2").CopyFromRecordset rs
  End If
  rs.Close:    Set rs = Nothing
  cn.Close:    Set cn = Nothing
End Sub
 
Chỉnh lại
Mã:
Sub ABC()
  Dim cn As Object, rs As Object, SQL As String

  Set cn = CreateObject("ADODB.Connection")
  cn.Open ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0;HDR=no""")
  SQL = "Select * From [DATA$] Where IIf(Mid(f1,7,2)=99,Mid(f1,1,6)&""00"",f1) = (Select Max(IIf(Mid(f1,7,2)=99,Mid(f1,1,6)&""00"",f1)) From [DATA$])"
  Set rs = cn.Execute(SQL)
  If Not rs.EOF() Then
    Sheets("sheet1").Range("A2").CopyFromRecordset rs
  End If
  rs.Close:    Set rs = Nothing
  cn.Close:    Set cn = Nothing
End Sub

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 ở đây thôi.

Xin chào Bác HieuCD,
Code trên của Bác con thử chạy được rồi ạ, cảm ơn Bác Hiếu.

Xin chào Hau151978,
Cảm ơn Bạn, OT đã sửa lại câu lệnh connection strings theo link bạn gửi kèm rồi ạ.
Kết quả vẫn lấy được số liệu.. hay thậy có thể do OT sử dụng phiên bản Office 365 nên có gì đó khác khác.
OT chưa thử các phiên bản office khác.
 
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 đề.
 
Xin chào các Bạn,

Nhờ các Bạn giúp đỡ OT sử dụng ADO/SQL để thực hiện trường hợp sau với ạ:
Từ bảng "DULIEU" lọc duy nhất 3 cột MAHANG,TENHANG,CHUNGLOAI,sau đó tính tổng số lượng theo vùng công thức màu hồng tím dựa vào điều kiện từ ngày đến ngày. Kết quả mong như bảng "TH_MH" ạ.
OT sử dụng câu lệnh "SELECT DISTINCT MAHANG,TENHANG,CHUNGLOAI" thì lấy được dữ liệu duy nhất của 3 trường, nhưng chưa biết cách tính toán cho vùng công thức màu hồng ạ.


DL.jpg

TH.jpg
 

File đính kèm

  • THMH.xlsx
    103.8 KB · Đọc: 9
Xin chào các Bạn,

Nhờ các Bạn giúp đỡ OT sử dụng ADO/SQL để thực hiện trường hợp sau với ạ:
Từ bảng "DULIEU" lọc duy nhất 3 cột MAHANG,TENHANG,CHUNGLOAI,sau đó tính tổng số lượng theo vùng công thức màu hồng tím dựa vào điều kiện từ ngày đến ngày. Kết quả mong như bảng "TH_MH" ạ.
OT sử dụng câu lệnh "SELECT DISTINCT MAHANG,TENHANG,CHUNGLOAI" thì lấy được dữ liệu duy nhất của 3 trường, nhưng chưa biết cách tính toán cho vùng công thức màu hồng ạ.


View attachment 236068

View attachment 236069
Không biết ADO, viết bằng VBA được không?
 

File đính kèm

  • THMH.rar
    49.4 KB · Đọc: 8
Không biết ADO, viết bằng VBA được không?
Con chào Thầy ạ,
Dạ được chứ Thầy, vì hiện giờ con đang sử dụng công thức ạ. Về dạng dữ liệu kiểu này con đang sử dụng nhiều, Vba có thể ứng dụng đư nhiều tình huống khác ạ.
Con muốn hỏi thêm phương pháp ADO/SQL để lấy dữ liệu trực tiếp từ SQL_Server mà không cần phải đưa dữ liệu về Excel nữa .
Con cảm ơn Thầy nhiều ạ,
Chúc Thầy nhiều sức khỏe ạ.
 
Xin chào các Bạn,

Nhờ các Bạn giúp đỡ OT sử dụng ADO/SQL để thực hiện trường hợp sau với ạ:
Từ bảng "DULIEU" lọc duy nhất 3 cột MAHANG,TENHANG,CHUNGLOAI,sau đó tính tổng số lượng theo vùng công thức màu hồng tím dựa vào điều kiện từ ngày đến ngày. Kết quả mong như bảng "TH_MH" ạ.
OT sử dụng câu lệnh "SELECT DISTINCT MAHANG,TENHANG,CHUNGLOAI" thì lấy được dữ liệu duy nhất của 3 trường, nhưng chưa biết cách tính toán cho vùng công thức màu hồng ạ.


View attachment 236068

View attachment 236069
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
 
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

Xin chào quanluu1989,
Cảm ơn Bạn đã góp ý, đúng là khi lấy một lượng dữ liệu lớn từ máy chủ về thì nên thực hiện trực tiếp qua Sever ạ.
Vba trong trường hợp này vẫn có thể sử dụng được ạ,nếu dữ liệu không quá nhiều(khoảng hai trăm nghìn dòng trở xuống- do số lượng bản ghi đã khống chế từ câu lệnh lấy dữ liệu từ mày chủ).
Nhưng để đảm bảo có thể tổng hợp dữ liệu ở một khoảng thời gian dài thì việc sử dụng vba có thể sẽ bị treo do dữ liệu lấy về quá nhiều ạ.
Với ví dụ trên OT chưa hiểu và nắm bắt được phiền bạn giúp đỡ OT làm viết câu lệnh select theo tất cả điều kiện tín toán trong cột "TONG CONG" được không ạ.
Cảm ơn Bạn nhiều.
 
Web KT
Back
Top Bottom