0
votes

Comment transformer le SQL complexe en linq

Pour un certain temps, j'essaie de transformer ce SQL en Linq:

var directorArr = new (int, string)[] { (1, "Bebopvsky"), (2, "Tarrantino"), (3, "CubeRick") };
            var actorArr = new (int, string, int)[] 
            {   (1, "Dat Maan",75), (2, "That Man", 28),
                (3, "Dat Women", 32), (4, "That Women", 22),
                (5, "Already Women", 12) };
            var moviesArr = new (int, string, int, DateTime, int, int)[] 
            {   (1, "Platform for soul", 121, Convert.ToDateTime("2018-12-31"), 2, 9),
                (2, "Full-featured access management", 42, Convert.ToDateTime("2019-01-01"), 3, 7),
                (3, "Robust LDAP server for Java", 13, Convert.ToDateTime("2005-05-25"), 3, 4),
                (4, "Man of Rain", 114, Convert.ToDateTime("2004-07-21"), 1, 10),
                (5, "Man of Arms", 152, Convert.ToDateTime("2003-02-17"), 1, 9),
                (6, "Man of War", 93, Convert.ToDateTime("2017-07-05"), 2, 8),
                (7, "Man of Legs", 33, Convert.ToDateTime("2018-11-11"), 1, 9),
                (8, "Mof", 55, Convert.ToDateTime("2015-11-11"), 2, 8) };
            var movieActorArr = new (int, int)[] 
            {   (1,1), (1,3), (1,4), (1,5),
                (2,1), (2,5),
                (3,4),
                (4,1), (4,2), (4,3), (4,4),
                (5,1), (5,2), (5,3), (5,4), (5,5),
                (6,1), (6,2), (6,3),
                (7,2), (7,4), (7,5),
                (8,1), (8,4) };


4 commentaires

Vous voulez donc le nom des administrateurs qui ont dirigé 3 à 7 acteurs et avoir deux films ou plus de plus de 60 minutes?


Quel fournisseur LINQ utilisez-vous? Linq aux objets? LINQ vers l'ensemble de l'entité (et quelle version de EF si oui)? Pouvez-vous publier vos modèles C # afin qu'il soit plus facile pour nous de reproduire?


@Hogan Directors, qui a dirigé 2 films ou plus de plus de 60 minutes à chacun desquels 3 à 7 acteurs ont participé. Maintenant, im Thinkig, que ma requête SQL a également besoin de changements.


@ 42ama ouais votre SQL était faux.


3 Réponses :


0
votes

Si vous avez besoin d'obtenir un nom d'administrateur, ce qui a dirigé 2 films ou plus de plus de 60 minutes dans chacun desquels 3 à 7 acteurs ont participé (comme vous l'avez dit dans votre commentaire), essayez ceci:

// use group join to get movies with duration > 60 min
var filteredMovies = 
    from d in directors
    join m in movies.Where(x => x.DurationMinutes >= 60 && x.ReleaseDate <= new DateTime(2015, 12, 31) && x.Rating >= 9)
    on  d.Id equals m.DirectorId into groupMovies
    let moviesCountForEachDirector = groupMovies.Count()
    where moviesCountForEachDirector > 1
    select groupMovies;

// use group join to get movies with actors from 3 to 7
var moviesWithActors = 
    from m in filteredMovies.SelectMany(x => x)
    join ma in movieActor on m.MovieId equals ma.MovieId into groupJoin
    let actorsInEachMovieCount = groupJoin.Count()
    where actorsInEachMovieCount > 2 && actorsInEachMovieCount < 8
    select new 
    {
        MovieId = m.MovieId,
    };

// the rest of query
var query = 
    from d in directors
    join m in movies on d.Id equals m.DirectorId
    join ma in moviesWithActors on m.MovieId equals ma.MovieId
    group d by d.Id into gr 
    select new { DirectorName = gr.First().Name };


0 commentaires

0
votes

Enfin, je suis venu avec une solution. Tout d'abord, j'ai changé la requête SQL (avec une aide supplémentaire): xxx pré>

puis dans l'image modyfied linq requête. P>

var query4 = (from x in 
                 (from d in directors
                     join m in movies2 
                         on d.Id equals m.DirectorId
                     join ma in movieActors 
                         on m.Id equals ma.MovieId
                     where m.ReleaseDate <= Convert.ToDateTime("2005-12-31")
                     where m.Rating >= 9
                     where m.DurationMinutes >= 60
                     group d by new { d.Name, m.Id } into res
                         where res.Count() >= 3
                         where res.Count() <= 7
                         select res)
                 group x by x.Key.Name into fin
                     where fin.Count() >= 2
                     select fin)
                 ;


0 commentaires

0
votes

Il me défle toujours, que si les gens ont une exigence dont ils ont besoin de résoudre à l'aide de Linq, ils ne nous donnent pas la nécessité, mais traduisent d'abord l'exigence dans SQL et nous donner le SQL au lieu de l'exigence.

Il me semble que vous souhaitez une déclaration LINQ qui renvoie ce qui suit: P>

Donnez-moi tous les noms des réalisateurs qui ont dirigé des films sur ou avant une date code> code>, avec une note supérieure ou égale qu'un certain numéro de notation, pour au moins 2 films plus longs d'au moins une heure, avec au moins 3 et au plus 7 acteurs p> blockQuote>

Si vous avez des relations un à plusieurs ou plusieurs à plusieurs entre tables, et que vous souhaitez "articles avec leurs nombreux sous-éléments" comme des écoles avec leurs étudiants, des clients avec leurs commandes, des commandes avec Leurs lignes de charge, vous devriez penser à utiliser Enumérable.Groupjoin P>

Si d'autre part, vous voulez que le sous-élément avec celui qu'il appartient, comme l'étudiant avec la seule et unique école qu'il fréquente, Ou la commande avec le client unique et unique qui a placé cette commande, utilisez énumérable.join p>

Dans ce cas, nous voulons des administrateurs avec ses films, nous allons donc utiliser groupjoin. P>

TimeSpan oneHour = TimeSpan.FromHours(1);
var result = directors.GroupJoin(movies,
    director => director.Id,              // from each director take the Id
    movie => movie.DirectorId             // from each movie take the DirectorId

    // result selector: take every director with all his movies to make one new:
    (director, moviesOfThisDirector) => new
    {
        // from the director we only need his name
        Name = director.Name

        // From each of his movies we need the ReleaseDate, the Rating and the number of actors
        Movies = moviesOfThisDirector.Select(movie => new
        {
            ReleaseDate = movie.ReleaseDate,
            Rating = movie.Rating,
            Duration = movie.Duration,

            NumberOfActors = movie.GroupJoin(actors,
                movie => movie.Id,
                actor => actor.MovieId,

                // ResultSelector: only count all Actors in this movie
                (movie, actorsInThisMovie) => actorInThisMovie.Count(),
        })
        // well, we don't want all movies,
        // we only want movies before a date with a high rating and a certain duration
        .Where(movie => movie.ReleaseDate <= myDate
                     && movie.Rating >= myRating
                     && movie.Duration >= oneHour),
    })
    // we don't want all Directors, we only want those that have at least one such a movie
    .Where(directory => directory.Movies.Any();


1 commentaires

Il y a une virgule manquante après move.directid et un extra sur deux places. Votre échantillon de code ne compilerait pas.