2013-09-06 108 views
21

Tôi đang tìm các giải pháp thay thế cho vlookup, với hiệu suất được cải thiện trong bối cảnh quan tâm.Làm cách nào để tối ưu hóa vlookup cho số lượng tìm kiếm cao? (các lựa chọn thay thế cho VLOOKUP)

Bối cảnh là như sau:

  • tôi có một tập hợp dữ liệu {then chốt; dữ liệu} đó là lớn (~ 100.000 hồ sơ)
  • Tôi muốn thực hiện rất nhiều hoạt động VLOOKUP trên tập dữ liệu (sử dụng điển hình là để sắp xếp lại toàn bộ dữ liệu)
  • bộ dữ liệu của tôi không có chìa khóa trùng lặp
  • tôi đang tìm kiếm chỉ cho kết hợp chính xác (đối số cuối cùng để VLOOKUPFALSE)

Một schema để giải thích:

tấm

tham khảo: ("sheet1")

 A   B 
    1 
    2 key1  data1 
    3 key2  data2 
    4 key3  data3 
    ... ...   ... 
99999 key99998 data99998 
100000 key99999 data99999 
100001 key100000 data100000 
100002 

Lookup tờ:

 A   B 
    1 
    2 key51359 =VLOOKUP(A2;sheet1!$A$2:$B$100001;2;FALSE) 
    3 key41232 =VLOOKUP(A3;sheet1!$A$2:$B$100001;2;FALSE) 
    4 key10102 =VLOOKUP(A3;sheet1!$A$2:$B$100001;2;FALSE) 
    ... ...   ... 
99999 key4153  =VLOOKUP(A99999;sheet1!$A$2:$B$100001;2;FALSE) 
100000 key12818 =VLOOKUP(A100000;sheet1!$A$2:$B$100001;2;FALSE) 
100001 key35032 =VLOOKUP(A100001;sheet1!$A$2:$B$100001;2;FALSE) 
100002 

Trên Core tôi i7 M 620 @ 2,67 GHz, này tính trong ~ 10 phút

Có các lựa chọn thay thế cho VLOOKUP có hiệu suất tốt hơn trong ngữ cảnh này không?

+0

với tập dữ liệu lớn như vậy thì Excel có thể không phải là lựa chọn tốt. Sử dụng một cơ sở dữ liệu chuyên nghiệp như * SQL hoặc truy cập MS sẽ tốt hơn nhiều –

Trả lời

20

tôi coi là lựa chọn thay thế sau:

  • VLOOKUP mảng công thức
  • Đội hình thi đấu/INDEX
  • VBA (sử dụng một cuốn từ điển)

Việc thực hiện so là:

  • VLOOKUP công thức đơn giản: ~ 10 phút s
  • VLOOKUP mảng công thức: ~ 10 phút (1: 1 hiệu suất index)
  • Đội hình thi đấu/INDEX: ~ 2 phút (5: 1 chỉ số hiệu suất)
  • VBA (sử dụng một cuốn từ điển): ~ 6 giây (100: chỉ số 1 hiệu suất)

Sử dụng tờ tài liệu tham khảo cùng

1) tấm Lookup: (mảng VLOOKUP thức phiên bản)

  A   B 
    1 
    2 key51359 {=VLOOKUP(A2:A10001;sheet1!$A$2:$B$100001;2;FALSE)} 
    3 key41232 formula in B2 
    4 key10102 ... extends to 
    ... ...   ... 
99999 key4153  ... cell B100001 
100000 key12818 ... (select whole range, and press 
100001 key35032 ... CTRL+SHIFT+ENTER to make it an array formula) 
100002 

2) tấm Lookup: (trận đấu + chỉ số phiên bản)

  A   B          C 
     1 
     2 key51359 =MATCH(A2;sheet1!$A$2:$A$100001;)  =INDEX(sheet1!$B$2:$B$100001;B2) 
     3 key41232 =MATCH(A3;sheet1!$A$2:$A$100001;)  =INDEX(sheet1!$B$2:$B$100001;B3) 
     4 key10102 =MATCH(A4;sheet1!$A$2:$A$100001;)  =INDEX(sheet1!$B$2:$B$100001;B4) 
    ... ...   ...          ... 
    99999 key4153  =MATCH(A99999;sheet1!$A$2:$A$100001;) =INDEX(sheet1!$B$2:$B$100001;B99999) 
100000 key12818 =MATCH(A100000;sheet1!$A$2:$A$100001;) =INDEX(sheet1!$B$2:$B$100001;B100000) 
100001 key35032 =MATCH(A100001;sheet1!$A$2:$A$100001;) =INDEX(sheet1!$B$2:$B$100001;B100001) 
100002 

3) tấm Lookup: (vbalookup phiên bản)

 A   B 
    1 
    2 key51359 {=vbalookup(A2:A50001;sheet1!$A$2:$B$100001;2)} 
    3 key41232 formula in B2 
    4 key10102 ... extends to 
    ... ...   ... 
50000 key91021 ... 
50001 key42  ... cell B50001 
50002 key21873 {=vbalookup(A50002:A100001;sheet1!$A$2:$B$100001;2)} 
50003 key31415 formula in B50001 extends to 
    ... ...   ... 
99999 key4153  ... cell B100001 
100000 key12818 ... (select whole range, and press 
100001 key35032 ... CTRL+SHIFT+ENTER to make it an array formula) 
100002 

NB: Đối với một số lý do (bên ngoài nội bộ), các vbalookup thất bại để trả lại hơn 65536 dữ liệu cùng một lúc. Vì vậy, tôi đã phải chia công thức mảng thành hai.

và mã VBA liên quan:

Function vbalookup(lookupRange As Range, refRange As Range, dataCol As Long) As Variant 
    Dim dict As New Scripting.Dictionary 
    Dim myRow As Range 
    Dim I As Long, J As Long 
    Dim vResults() As Variant 

    ' 1. Build a dictionnary 
    For Each myRow In refRange.Columns(1).Cells 
    ' Append A : B to dictionnary 
    dict.Add myRow.Value, myRow.Offset(0, dataCol - 1).Value 
    Next myRow 

    ' 2. Use it over all lookup data 
    ReDim vResults(1 To lookupRange.Rows.Count, 1 To lookupRange.Columns.Count) As Variant 
    For I = 1 To lookupRange.Rows.Count 
    For J = 1 To lookupRange.Columns.Count 
     If dict.Exists(lookupRange.Cells(I, J).Value) Then 
     vResults(I, J) = dict(lookupRange.Cells(I, J).Value) 
     End If 
    Next J 
    Next I 

    vbalookup = vResults 
End Function 

NB: Scripting.Dictionary đòi hỏi một referenc để Microsoft Scripting Runtime mà phải thêm bằng tay (Tools-> đơn Tài liệu tham khảo trong cửa sổ Excel VBA)

Kết luận:

Trong ngữ cảnh này, VBA sử dụng từ điển nhanh hơn 100 lần so với sử dụng VLOOKUP và nhanh hơn 20 lần so với MATCH/INDEX

+3

Tôi đang cố gắng sử dụng vbalookup của bạn để thay thế chức năng vlookup trong excel của tôi. Tôi có dữ liệu trong một tab và các công thức khác nhau trong tab khác. nếu tôi đã nhận nó đúng tôi nên sử dụng trong cùng một cú pháp như vlookup: vlookup (giá trị, phạm vi, col). Bây giờ, đây là vấn đề: nó luôn trả về giá trị #value của tôi. Bạn có thấy giống nhau không? – fatSlave

+1

Thay vì khai báo nó như là một scripting.dictionary bạn cũng có thể sử dụng Set dict = CreateObject ("Scripting.Dictionary"), điều này không yêu cầu tham chiếu VBA bổ sung và mã tương thích với cài đặt VBA mặc định –

+0

Nếu ai đó tìm thấy Trả lời câu hỏi của FatSlave, vui lòng đăng câu hỏi tại đây: https://stackoverflow.com/questions/48209023/avoid-the-value-error-when-using-a-vlookup-with-scrypting-dictionary – Pierre44

5

Bạn cũng có thể muốn xem xét sử dụng phương pháp "đôi Vlookup" (không phải ý tưởng của tôi - được thấy ở nơi khác). Tôi đã thử nghiệm nó trên 100.000 giá trị tra cứu trên trang tính 2 (được sắp xếp ngẫu nhiên) với một tập dữ liệu giống hệt như tập dữ liệu bạn đã mô tả trên trang tính 1 và đã hẹn giờ nó chỉ dưới 4 giây. Mã này cũng đơn giản hơn một chút.

Sub FastestVlookup() 

    With Sheet2.Range("B1:B100000") 
     .FormulaR1C1 = _ 
     "=IF(VLOOKUP(RC1,Sheet1!R1C1:R100000C1,1)=RC1,VLOOKUP(RC1,Sheet1!R1C1:R100000C2,2),""N/A"")" 
     .Value = .Value 
    End With 

End Sub 
+0

Bạn có thể giải thích mã một chút. Những thay đổi nên được thực hiện? – davejal

+0

Tất cả các trường nhận được giá trị này: "# NAME?" – davejal

+0

Nếu bạn nhận được "#NAME?" lỗi, rất có thể bạn đã viết sai chính tả "VLOOKUP" trong mã của mình hoặc bạn có dấu "(" ở sai địa điểm. Hãy kiểm tra và thử lại. – kevin9999

4

Chuyển sang Excel 2013 và sử dụng Mô hình dữ liệu. Ở đó bạn có thể xác định một cột có các khóa ID duy nhất trong cả hai bảng và liên kết hai bảng đó với mối quan hệ trong Bảng Pivot. Hơn nữa, nếu cần thiết, bạn có thể sử dụng Getpivotdata() để điền vào bảng đầu tiên. Tôi đã có một bảng hàng 250K làm vlookup trong bảng hàng 250K tương tự. Ngưng Excel tính toán nó sau một giờ. Với Mô hình Dữ liệu, nó mất ít hơn 10 giây.

-1

Sửa lỗi: kiểm tra ô trống khi tạo từ điển. Nếu ô trống, thoát cho.