Pergunta

Eu tenho uma lista que se parece com:

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

Usando CAML eo objeto SPQuery eu preciso para obter uma lista distinta de itens da coluna Ano que povoam um drop-down controle.

Como pesquisar em torno de lá não parece ser uma maneira de fazer isso dentro da consulta CAML. Eu estou querendo saber como as pessoas têm ido sobre a realização isso?

Foi útil?

Solução

Outra maneira de fazer isso é usar DataView.ToTable-Método -. Seu primeiro parâmetro é o que faz com que a lista distinta

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

Você pode então prosseguir com o tbl DataTable.

Outras dicas

Se você deseja vincular os resultados distintos para uma fonte de dados de, por exemplo, um repetidor e reter o item real através do método e.Item.DataItem os eventos ItemDataBound, a maneira DataTable não está indo para o trabalho. Em vez disso, e além disso também quando não querendo vinculá-lo a uma fonte de dados, você também pode usar Linq para definir os valores distintos.

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

Lembre-se que uma vez que não há apoio CAML para consultas distintos, cada amostra fornecidas nesta página irá recuperar todos os itens da SPList. Isso pode ser bom para listas menores, mas para listas com milhares de listitems, este será seriamente um assassino de desempenho. Infelizmente não há maneira de alcançar o mesmo não mais otimizado.

Não há DISTINCT em CAML para preencher a sua tentativa suspensa usando algo como:

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

assume que o seu suspensa é chamado ddlYear.

Você pode mudar de SPQuery para SPSiteDataQuery? Você deve ser capaz de, sem quaisquer problemas.

Depois disso, você pode usar o comportamento ado.net padrão:

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

Depois de encontrar cargo após post sobre como isso era impossível, eu finalmente encontrei uma maneira. Este foi testado no SharePoint Online. Aqui está uma função que você vai ter todos os valores exclusivos de uma coluna. Ela exige apenas que você passe na lista de Id, Vista Id, nome da lista interna, e uma função de retorno de chamada.

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

}

Eu estava a considerar este problema mais cedo hoje, ea melhor solução que eu poderia pensar de usos o seguinte algoritmo (desculpe, nenhum código no momento):

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

Isto reduziria o número total de itens devolvidos significativamente, ao custo de fazer mais consultas.

Ele não importa muito se X é inteiramente correta, mas a aleatoriedade é muito importante. Essencialmente a primeira consulta é provável que incluem a maioria das opções comuns, então a segunda consulta irá excluir esses e é provável que incluem as opções mais comuns próxima e assim por diante através das iterações.

No melhor dos casos, a primeira consulta inclui todas as opções, em seguida, a segunda consulta estará vazia. (X itens recuperados no total, mais de 2 consultas)

No pior dos casos (por exemplo, a consulta é ordenada pelas opções que estamos procurando, e há mais de X itens com cada opção) vamos fazer tantas perguntas, pois há opções. Retornando aproximadamente X * X itens no total.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top