使用SPQuery检索不同/唯一值的最佳方法是什么?

时间:2009-02-18 10:39:18

标签: sharepoint caml spquery

我有一个类似的列表:

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

使用CAML和SPQuery对象,我需要从Year列中获取一个不同的项目列表,它将填充下拉控件。

在CAML查询中搜索周围似乎没有这样做的方法。我想知道人们是如何实现这一目标的?

6 个答案:

答案 0 :(得分:13)

另一种方法是使用DataView.ToTable-Method - 它的第一个参数是使列表不同的参数。

            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);

然后,您可以继续使用DataTable tbl。

答案 1 :(得分:5)

如果要将不同的结果绑定到例如Repeater的DataSource并通过ItemDataBound事件的e.Item.DataItem方法保留实际项,则DataTable方式不起作用。相反,除了不想将它绑定到DataSource之外,您还可以使用Linq来定义不同的值。

// 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();

请记住,由于不存在对不同查询的CAML支持,因此此页面上提供的每个示例都将从SPList中检索所有项目。这可能适用于较小的列表,但对于包含数千个列表项的列表,这将严重影响性能。不幸的是,没有更好的方法来实现同样的目标。

答案 2 :(得分:2)

CAML中没有DISTINCT来填充您的下拉列表尝试使用类似:

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);
        }
   }

假设您的下拉列表名为ddlYear。

答案 3 :(得分:1)

您可以从SPQuery切换到SPSiteDataQuery吗?你应该没有任何问题。

之后,您可以使用标准的ado.net行为:

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");

答案 4 :(得分:1)

After coming across post after post about how this was impossible, I've finally found a way. This has been tested in SharePoint Online. Here's a function that will get you all unique values for a column. It just requires you to pass in the list Id, View Id, internal list name, and a callback function.

t.test

}

答案 5 :(得分:0)

我今天早些时候正在考虑这个问题,我能想到的最好的解决方案是使用以下算法(抱歉,目前没有代码):

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

这将减少显着返回的项目总数,但需要进行更多查询。

如果X完全准确并不重要,但随机性非常重要。本质上,第一个查询可能包含最常见的选项,因此第二个查询将排除这些选项,并且可能包含下一个最常见的选项,依此类推。

在最好的情况下,第一个查询包含所有选项,然后第二个查询将为空。 (总共检索了X个项目,超过2个查询)

在最糟糕的情况下(例如,查询按我们正在寻找的选项排序,并且每个选项都有超过X个项目),我们将根据选项进行尽可能多的查询。总共返回大约X * X个项目。