Каков наилучший способ получения уникальных / уникальных значений с помощью SPQuery? - PullRequest
15 голосов
/ 18 февраля 2009

У меня есть список, который выглядит так:

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

Используя CAML и объект SPQuery, мне нужно получить отдельный список элементов из столбца Год, который заполнит раскрывающийся элемент управления.

Поиск там, похоже, не является способом сделать это в запросе CAML. Мне интересно, как люди добились этого?

Ответы [ 6 ]

13 голосов
/ 18 февраля 2009

Другой способ сделать это - использовать 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);

Затем вы можете продолжить использование таблицы данных.

5 голосов
/ 29 декабря 2010

Если вы хотите связать отдельные результаты с источником данных, например, с повторителем, и сохранить фактический элемент с помощью метода e.Item.DataItem событий ItemDataBound, метод DataTable работать не будет. Вместо этого, кроме того, когда вы не хотите связывать его с источником данных, вы также можете использовать 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 голосов
/ 18 февраля 2009

В 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.

1 голос
/ 30 августа 2017

Перебрав пост за постом о том, как это было невозможно, я наконец нашел способ. Это было проверено в SharePoint Online. Вот функция, которая выдаст вам все уникальные значения для столбца. Для этого просто необходимо передать идентификатор списка, идентификатор просмотра, имя внутреннего списка и функцию обратного вызова.

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

}

1 голос
/ 18 февраля 2009

Можете ли вы переключиться с 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");
0 голосов
/ 24 ноября 2012

Я рассматривал эту проблему ранее сегодня, и лучшее решение, которое я мог придумать, использует следующий алгоритм (извините, на данный момент нет кода):

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 элементов в общей сложности.

...