2009-02-18 34 views
15

Tôi có một danh sách giống như:Cách tốt nhất để lấy các giá trị khác biệt/duy nhất bằng cách sử dụng SPQuery là gì?

Movie   Year 
-----   ---- 
Fight Club  1999 
The Matrix  1999 
Pulp Fiction 1994 

Sử dụng CAML và đối tượng SPQuery tôi cần để có được một danh sách riêng biệt các mặt hàng từ cột Năm đó sẽ cư một danh sách thả xuống kiểm soát.

Tìm kiếm xung quanh dường như không phải là cách để thực hiện việc này trong truy vấn CAML. Tôi tự hỏi làm thế nào mọi người đã đi về việc đạt được điều này?

Trả lời

13

Một cách khác để làm điều này là sử dụng DataView.ToTable-Phương pháp - Tham số đầu tiên của nó là một trong đó làm cho danh sách riêng biệt.

  SPList movies = SPContext.Current.Web.Lists["Movies"]; 
      SPQuery query = new SPQuery(); 
      query.Query = "<OrderBy><FieldRef Name='Year' /></OrderBy>"; 

      DataTable tempTbl = movies.GetItems(query).GetDataTable(); 
      DataView v = new DataView(tempTbl); 
      String[] columns = {"Year"}; 
      DataTable tbl = v.ToTable(true, columns); 

Sau đó, bạn có thể tiếp tục sử dụng DataTable tbl.

+2

Mặc dù điều này đã được đánh dấu là câu trả lời, phương pháp này vẫn dựa vào lấy mỗi mục trong danh sách từ cơ sở dữ liệu và sau đó * * tìm kiếm những giá trị độc đáo. Tôi nghĩ rằng toàn bộ vấn đề yêu cầu làm thế nào để thực hiện nó trong CAML là tránh lấy mọi mục từ cơ sở dữ liệu ... – MgSam

+2

Tôi đồng ý với MgSam, vì CAML không thực sự thay thế cho ngôn ngữ truy vấn thực tế như SQL. Điều này là tốt như nó được. Và câu trả lời này sẽ chuyển cuộc hội thoại về phía trước. +1 từ tôi. –

2

Không có DISTINCT trong CAML để cư thả xuống bạn hãy thử sử dụng một cái gì đó như:

foreach (SPListItem listItem in listItems) 
    { 
     if (null == ddlYear.Items.FindByText(listItem["Year"].ToString())) 
     { 
        ListItem ThisItem = new ListItem(); 
        ThisItem.Text = listItem["Year"].ToString(); 
        ThisItem.Value = listItem["Year"].ToString(); 
        ddlYear.Items.Add(ThisItem); 
     } 
    } 

Giả thả xuống của bạn được gọi ddlYear.

1

Bạn có thể chuyển từ SPQuery sang SPSiteDataQuery không? Bạn sẽ có thể, mà không có bất kỳ vấn đề.

Sau đó, bạn có thể sử dụng hành vi ado.net tiêu chuẩn:

SPSiteDataQuery query = new SPSiteDataQuery(); 
/// ... populate your query here. Make sure you add Year to the ViewFields. 

DataTable table = SPContext.Current.Web.GetSiteData(query); 

//create a new dataview for our table 
DataView view = new DataView(table); 

//and finally create a new datatable with unique values on the columns specified 

DataTable tableUnique = view.ToTable(true, "Year"); 
5

Nếu bạn muốn ràng buộc các kết quả riêng biệt với một nguồn dữ liệu ví dụ như một Repeater và giữ lại mục thực tế thông qua phương thức e.Item.DataItem của sự kiện ItemDataBound, cách DataTable sẽ không hoạt động. Thay vào đó, và ngoài ra khi không muốn kết buộc nó vào một DataSource, bạn cũng có thể sử dụng LINQ để xác định các giá trị khác biệt.

// Retrieve the list. NEVER use the Web.Lists["Movies"] option as in the other examples as this will enumerate every list in your SPWeb and may cause serious performance issues 
var list = SPContext.Current.Web.Lists.TryGetList("Movies"); 

// Make sure the list was successfully retrieved 
if(list == null) return; 

// Retrieve all items in the list 
var items = list.GetItems(); 

// Filter the items in the results to only retain distinct items in an 2D array 
var distinctItems = (from SPListItem item in items select item["Year"]).Distinct().ToArray() 

// Bind results to the repeater 
Repeater.DataSource = distinctItems; 
Repeater.DataBind(); 

Hãy nhớ rằng vì không có hỗ trợ CAML cho các truy vấn riêng biệt, mỗi mẫu được cung cấp trên trang này sẽ truy lục TẤT CẢ các mục từ SPList. Điều này có thể tốt cho các danh sách nhỏ hơn, nhưng đối với các danh sách có hàng nghìn danh sách, điều này sẽ nghiêm trọng là một kẻ giết người hiệu suất. Thật không may là không có cách nào tối ưu hơn để đạt được như vậy.

0

Tôi đã xem xét vấn đề này trước ngày hôm nay, và là giải pháp tốt nhất mà tôi có thể nghĩ đến sử dụng thuật toán sau đây (xin lỗi, không có mã số vào lúc này):

L is a list of known values (starts populated with the static Choice options when querying fill-in options, for example) 
X is approximately the number of possible options 

1. Create a query that excludes the items in L 
1. Use the query to fetch X items from list (ordered as randomly as possible) 
2. Add unique items to L 
3. Repeat 1 - 3 until number of fetched items < X 

này sẽ làm giảm tổng số các mặt hàng trở lại đáng kể, với chi phí tạo nhiều truy vấn hơn.

Nó không quan trọng nếu X là hoàn toàn chính xác, nhưng sự ngẫu nhiên là khá quan trọng. Về cơ bản, truy vấn đầu tiên có khả năng bao gồm các tùy chọn phổ biến nhất, do đó truy vấn thứ hai sẽ loại trừ các truy vấn này và có khả năng bao gồm các tùy chọn phổ biến nhất tiếp theo, v.v ... qua các lần lặp.

Trong trường hợp tốt nhất, truy vấn đầu tiên bao gồm tất cả các tùy chọn, khi đó truy vấn thứ hai sẽ trống. (X mục được truy xuất tổng cộng, hơn 2 truy vấn)

Trong trường hợp xấu nhất (ví dụ: truy vấn được sắp xếp theo các tùy chọn mà chúng tôi đang tìm kiếm và có nhiều hơn X mục với mỗi tùy chọn), chúng tôi sẽ thực hiện nhiều truy vấn như có các tùy chọn. Trả về tổng số X * X mục.

0

Sau khi xem qua bài đăng sau khi đăng bài về cách điều này là không thể, cuối cùng tôi đã tìm thấy một cách. Điều này đã được thử nghiệm trong SharePoint Online. Đây là một hàm sẽ giúp bạn có được tất cả các giá trị duy nhất cho một cột. Nó chỉ yêu cầu bạn chuyển vào Id danh sách, Id xem, tên danh sách nội bộ và chức năng gọi lại.

function getUniqueColumnValues(listid, viewid, column, _callback){ 
var uniqueVals = []; 
$.ajax({ 
    url: _spPageContextInfo.webAbsoluteUrl + "/_layouts/15/filter.aspx?ListId={" + listid + "}&FieldInternalName=" + column + "&ViewId={" + viewid + "}&FilterOnly=1&Filter=1", 
    method: "GET", 
    headers: { "Accept": "application/json; odata=verbose" } 
    }).then(function(response) { 
     $(response).find('OPTION').each(function(a,b){ 
      if ($(b)[0].value) { 
       uniqueVals.push($(b)[0].value); 
      } 
     }); 
     _callback(true,uniqueVals); 
},function(){ 
    _callback(false,"Error retrieving unique column values"); 
}); 

}

Các vấn đề liên quan