Quelle est la meilleure façon de récupérer les valeurs distinctes / uniques en utilisant SPQuery?

StackOverflow https://stackoverflow.com/questions/560550

  •  05-09-2019
  •  | 
  •  

Question

J'ai une liste qui ressemble à:

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

Utilisation CAML et l'objet SPQuery je dois obtenir une liste distincte des éléments de la colonne Année qui peupleront un menu déroulant contrôle.

autour de la recherche, il ne semble pas être un moyen de le faire dans la requête CAML. Je me demande comment les gens sont allés sur la réalisation de cela?

Était-ce utile?

La solution

Une autre façon de le faire est d'utiliser DataView.ToTable-Méthode -. Son premier paramètre est celui qui fait la liste distincte

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

Vous pouvez ensuite procéder à l'aide du TBL DataTable.

Autres conseils

Si vous voulez lier les résultats distincts à une source de données par exemple d'un répéteur et de conserver l'élément réel via la méthode de e.Item.DataItem des événements ItemDataBound, la façon dont DataTable ne va pas fonctionner. Au lieu de cela, et d'ailleurs aussi quand ne pas vouloir lier à une source de données, vous pouvez également utiliser LINQ pour définir les valeurs distinctes.

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

Souvenez-vous que, puisqu'il n'y a pas de support pour les requêtes CAML distinctes, chaque échantillon fourni sur cette page récupérera tous les éléments du SPList. Cela peut être très bien pour des listes plus petites, mais pour les listes avec des milliers de listitems, ce sera sérieusement un tueur de performance. Malheureusement, il n'y a pas plus optimisée moyen d'atteindre le même.

Il n'y a pas DISTINCT dans CAML pour peupler votre menu déroulant essayez d'utiliser quelque chose comme:

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

Suppose votre menu déroulant est appelé ddlYear.

Pouvez-vous passer de SPQuery à SPSiteDataQuery? Vous devriez pouvoir, sans aucun problème.

Après cela, vous pouvez utiliser le comportement standard 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");

Après avoir lu les post après post sur la façon dont cela était impossible, je l'ai finalement trouvé un moyen. Cela a été testé dans SharePoint Online. Voici une fonction qui vous permet d'obtenir toutes les valeurs uniques pour une colonne. Il n'a besoin que de passer dans la liste Id, Afficher Id, nom de la liste interne, et une fonction de rappel.

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

}

Je considérais ce problème plus tôt aujourd'hui, et la meilleure solution que je pouvais penser utilise l'algorithme suivant (désolé, pas de code pour le moment):

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

Cela réduirait le nombre total d'articles retournés de manière significative, au coût de fabrication plus de requêtes.

Il ne peu importe si X est tout à fait exact, mais le caractère aléatoire est très important. Essentiellement, la première requête est susceptible d'inclure des options les plus courantes, de sorte que la seconde requête exclut ceux-ci et est susceptible d'inclure les options suivantes les plus courantes et ainsi de suite à travers les itérations.

Dans le meilleur des cas, la première requête inclut toutes les options, puis la deuxième requête sera vide. (X éléments récupérés au total, plus de 2 requêtes)

Dans le pire des cas (par exemple, la requête est commandée par les options que nous recherchons, et il y a plus d'éléments X avec chaque option), nous ferons autant de questions car il y a des options. Retour d'articles environ X * X au total.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top