Базы данных конкурс


У меня есть следующие (весьма упрощенные) структуры базы данных:

  • Таблица: Конкурсы
    • Идентификатор: строка, уникальная
  • Таблица: Человек

    • Идентификатор: строка, уникальная
    • Пол: строку
  • Таблица: Результаты

    • CompetitionId: строка, ссылки идентификатор на соревнованиях таблица
    • PersonId: строка, ссылки идентификатор на лиц таблица
    • Код события: строку
    • RoundId: строку
    • Среднее: инт

Любой конкурс может провести Н результаты. Каждому результату присваивается одному человеку.

Хотелось бы получить все результаты (фильтрованный для среднего > 0, код события == "333", RoundId == "Ф", такую, что это один с самой низкой средней в другие результаты, имеющие одинаковые CompetitionId. Кроме того, я только хочу, чтобы получить результаты, которых по Человек женского пола (Пол == "Ф").

В настоящее время я использовать странные смешанные технологии LINQ конструкт, как, некрасиво и неэффективно. Запрос занимает около 3 минут на моей машине (местные базы данных MySQL, результаты подсчета строк что-то близкое к 200к).

Я знаю, что есть элегантные и эффективные способы использования одного запроса LINQ, создание временных таблиц, вступление и все такое. Я не так много на это, поэтому я написала этот уродливый кусок:

var femalePersonIds =
    from p in Persons
    where p.Gender == "f"
    select p.Id;

var results333 =
    from r in Results
    where (r.Average > 0) && (r.EventId == "333") && (r.RoundId == "f")
    orderby r.Average
    select r;

foreach (var c in Competitions) {
    var results =
        from r in results333
        where (r.CompetitionId == c.Id)
        select r;
    if (results.Count() > 0) {
        var bestCompResult = results.First();
        if (femalePersonIds.Contains(bestCompResult.PersonId)) {
            bestCompResult.Dump();
        }
    }
}

(Это уступчивый помощью linqpad 4)

Я бы с удовольствием поглядел эффективности, элегантности и укорочение подсказки, в случае если вы имеете некоторые.



1116
3
задан 10 августа 2011 в 01:08 Источник Поделиться
Комментарии
3 ответа

Я уверен, пару звонков в список решит ваши проблемы. Имейте в виду, что в каждом интервале цикла будет повторно оценить два запроса за пределы цикла.

var femalePersonIds =
(from p in Persons
where p.Gender == "f"
select p.Id).ToList();

var results333 =
(from r in Results
where (r.Average > 0) && (r.EventId == "333") && (r.RoundId == "f")
orderby r.Average
select r).ToList();

foreach (var c in Competitions) {
var results =
(from r in results333
where (r.CompetitionId == c.Id)
select r).ToList();
if (results.Count() > 0) {
var bestCompResult = results.First();
if (femalePersonIds.Contains(bestCompResult.PersonId)) {
bestCompResult.Dump();
}
}
}

2
ответ дан 10 августа 2011 в 02:08 Источник Поделиться

Попробуйте это:

        var filteredResults =
(from r in results
where r.Average > 0 &&
r.EventID == "333" &&
r.RoundID == "f"
select r).ToList();

List<Results> bestResults = new List<Results>();
var resultsInCompenitions = filteredResults.GroupBy(r => r.CompetitionID);
foreach (var resultsInCompetition in resultsInCompenitions)
{
var bestResultInCompetition = resultsInCompetition.OrderBy(r => r.Average).FirstOrDefault();
if (bestResultInCompetition != null)
{
bestResults.Add(bestResultInCompetition);
}
}

var femaleBestResults =
from r in bestResults
join p in persons on r.PersonID equals p.ID
where p.Gender == "f"
select r;

return femaleBestResults;

3
ответ дан 10 августа 2011 в 02:08 Источник Поделиться

Я может не совсем понимаю, что вы пытаетесь сделать, но вот пойти на это.

Results
.Where(r => r.Average > 0 && r.EventId == "333" && r.RoundId == "f")
.GroupBy(r => r.CompetitionId)
.Where(r => r.Any(z => z.Person.Gender == "f"))
.Dump();

0
ответ дан 10 августа 2011 в 05:08 Источник Поделиться