【问题标题】:What is the best way to retrieve distinct / unique values using SPQuery?使用 SPQuery 检索不同/唯一值的最佳方法是什么?
【发布时间】:2009-02-18 10:39:17
【问题描述】:

我有一个看起来像这样的列表:

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

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

在 CAML 查询中搜索似乎不是一种方法。我想知道人们是如何实现这一目标的?

【问题讨论】:

    标签: sharepoint caml spquery


    【解决方案1】:

    另一种方法是使用 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。

    【讨论】:

    • 即使这被标记为答案,此方法仍然依赖于从数据库中检索每个列表项并然后找到唯一值。我认为在 CAML 中询问如何做到这一点的全部目的是避免从数据库中检索每个项目......
    • 我同意 MgSam,但是,因为 CAML 不能真正替代 SQL 等实际查询语言。这是最好的。这个答案确实推动了对话。来自我的 +1。
    【解决方案2】:

    如果你想将不同的结果绑定到一个 DataSource,例如一个 Repeater,并通过 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 中检索所有项目。这对于较小的列表可能很好,但对于具有数千个列表项的列表,这将严重影响性能。不幸的是,没有更优化的方法可以达到同样的效果。

    【讨论】:

      【解决方案3】:

      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。

      【讨论】:

        【解决方案4】:

        您可以从 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");
        

        【讨论】:

          【解决方案5】:

          在看到一个又一个帖子说这是不可能的之后,我终于找到了一种方法。这已在 SharePoint Online 中进行了测试。这是一个可以为您获取列的所有唯一值的函数。它只需要您传入列表 ID、视图 ID、内部列表名称和回调函数。

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

          }

          【讨论】:

            【解决方案6】:

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

            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 个项目。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2015-04-08
              • 1970-01-01
              • 2011-06-29
              • 1970-01-01
              • 1970-01-01
              • 2021-01-14
              • 1970-01-01
              相关资源
              最近更新 更多