2009-02-18 12 views
15

Tengo una lista que se parece a:¿Cuál es la mejor manera de recuperar valores distintos/únicos utilizando SPQuery?

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

El uso de CAML y el objeto SPQuery que necesita para obtener una lista distinta de los elementos de la columna de Año que rellenar un control desplegable.

La búsqueda no parece ser una forma de hacerlo dentro de la consulta CAML. Me pregunto cómo han ido las personas para lograr esto.

Respuesta

13

Otra manera de hacer esto es utilizar DataView.ToTable-Método - su primer parámetro es el que hace que la 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); 

A continuación, puede continuar utilizando DataTable tbl.

+2

pesar de que este fue marcada como la respuesta, este método todavía se basa en la recuperación de cada elemento de la lista de la base de datos y luego * * la búsqueda de los valores únicos. Creo que todo el punto de preguntar cómo hacerlo en CAML es evitar la recuperación de todos los elementos de la base de datos ... – MgSam

+2

Estoy de acuerdo con MgSam, sin embargo, como CAML no es un verdadero sustituto de un lenguaje de consulta real como SQL. Esto es tan bueno como se pone. Y esta respuesta mueve la conversación hacia adelante. +1 de mi parte –

2

No hay DISTINCT en CAML para poblar el desplegable trate de usar 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); 
     } 
    } 

supone que su desplegable se llama ddlYear.

1

¿Se puede cambiar de SPQuery a SPSiteDataQuery? Deberías poder hacerlo, sin ningún problema.

Después de eso, se puede utilizar el comportamiento ado.net estándar:

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

Si desea vincular los distintos resultados a un DataSource de, por ejemplo, un Repeater y retener el elemento real a través del método e.Item.DataItem de los eventos de ItemDataBound, el método DataTable no funcionará. En cambio, y además, cuando no se desea vincularlo a un DataSource, también se puede usar Linq para definir los 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(); 

Recuerde que ya no hay apoyo para las consultas de CAML distintas, cada una muestra proporcionada en esta página recuperará todos los elementos de la SPList. Esto puede estar bien para listas más pequeñas, pero para listas con miles de elementos de lista, esto seriamente un asesino de rendimiento. Lamentablemente, no hay una forma más optimizada de lograr lo mismo.

0

estaba considerando este problema el día de hoy, y la mejor solución que se me ocurrió utiliza el siguiente algoritmo (lo siento, no hay código en el 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 

Esto reduciría el número total de artículos devueltos significativamente, a costa de hacer más consultas.

No importa mucho si X es completamente preciso, pero la aleatoriedad es bastante importante. Esencialmente, la primera consulta probablemente incluya las opciones más comunes, por lo que la segunda consulta las excluirá y es probable que incluya las siguientes opciones más comunes, y así sucesivamente a través de las iteraciones.

En el mejor de los casos, la primera consulta incluye todas las opciones, luego la segunda consulta estará vacía. (X elementos recuperados en total, más de 2 consultas)

En el peor de los casos (por ejemplo, la búsqueda está ordenada por las opciones que estamos buscando, y hay más de X elementos con cada opción) haremos como muchas consultas ya que hay opciones. Devolviendo aproximadamente X * X artículos en total.

0

Luego de descubrir cargo después de post acerca de cómo esto era imposible, por fin he encontrado una manera. Esto ha sido probado en SharePoint Online. Aquí es una función que les permite conocer todos los valores únicos de una columna. Sólo es necesario que indique el ID de lista, vista de ID, nombre de la lista interna, y una función de devolución de llamada.

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

}

Cuestiones relacionadas