LINQ unirse y agrupar

Soy nuevo en LINQ y estoy tratando de convertir esta consulta SQL en su equivalente LINQ:

select S.*
from Singles S
join (
    select max(SingleId) as SingleId
    from Single 
    group by ArtistId) S2 on S2.SingleId = S.SingleId
order by Released desc

La tabla se ve así:

 -----------
| Singles   |
|-----------|
| SingleID  |
| ArtistId  |
| Released  |
| Title     |
| .....     |
 -----------

y así sucesivamente ... Y contiene, por ejemplo, estos elementos:

SingleID   ArtistID    Released    Title
1          1           2011-05-10  Title1
2          1           2011-05-10  Title2
3          2           2011-05-10  Title3
4          3           2011-05-10  Title4
5          4           2011-05-10  Title5
6          2           2011-05-10  Title6
7          3           2011-05-10  Title7
8          5           2011-05-10  Title8
9          6           2011-05-10  Title9

Así que estoy tratando de conseguir los últimos singles, pero solo uno por artista. ¿Alguien podría ayudarme? :) ¿Quizás hay una forma mejor de escribir la consulta?

Actualizar:

Para responder a las preguntas publicadas en los comentarios: Estamos usando Microsoft SQL Server y LINQ to NHibernate.

Aquí hay una muestra que estamos usando en este momento, que devuelve los últimos singles, sin agrupar por artistid:

public Single[] GetLatest()
{
    IQueryable<Single> q;
    q = from s in _sess.Query<Single>()
        where s.State == State.Released
        orderby s.Released descending
        select s;

    return q.Take(20).ToArray();
}

preguntado el 10 de mayo de 11 a las 13:05

¿Es para SQL-Server u otro DBMS? -

¿Con que estás trabajando? ¿LINQ a SQL? ¿LINQ to Objects? Muéstranos el código que ya tienes. -

Actualizado para responder a sus preguntas. -

3 Respuestas

Qué tal esto:

var firstSingles = Singles.GroupBy(x => x.ArtistId)
                          .Select(g => g.OrderByDescending(x => x.Released).First())
                          .ToList();

contestado el 10 de mayo de 11 a las 17:05

Esto me da una excepción. [InvalidOperationException: se supone que el código es inalcanzable] System.Linq.Expressions.Compiler.StackSpiller.RewriteExpression (.... - AmITheRpalabra

@AmITheRWord: Después de una investigación rápida, parece que GroubBy en combinaciones con otros operadores puede ser la causa del problema (ver también stackoverflow.com/questions/5069925/…) - es un juego de adivinanzas cómo reescribir la consulta para que funcione. - Vidrio roto

¡Gracias! Ahora puedo seguir adelante, al menos. :) - AmITheRpalabra

Algo como esto debería funcionar.

var query = from s in db.Singles
            group s by s.ArtistID into sg
            let firstSingle = sg.OrderByDescending(r => r.SingleID).FirstOrDefault()
            select new
            {
              ArtistID = sg.Key,
              SingleID = firstSingle.SingleID,
              Released = firstSingle.Released,
              Title = firstSingle.Title,
            }

contestado el 10 de mayo de 11 a las 17:05

se puede utilizar el let palabra clave para definir una variable de rango en su consulta: let firstSingle = sg.OrderByDescending(r => r.SingleID).First(). - jeroenh

singles
    .OrderByDescending(s => s.SingleID)
    .GroupBy(s => s.SingerID, (id, s) => new
    {
         SingleID = id,
         Title = s.First().Title
    });

contestado el 10 de mayo de 11 a las 17:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.