В настоящее время у меня есть таблица в SQL людей с датой начала и окончания их проживания. Я хотел бы иметь возможность найти количество людей, живущих в этом месте за каждый год в списке лет.
Т.е.
Person, Start, End
A, 2013, 2014
B, 2013, 2015
C, 2014, 2015
Должен дать мне что-то вроде:
2012, 0
2013, 2
2014, 3
2015, 2
Моя проблема в том, что у меня нет списка лет, хранящихся где-либо в SQL. Мне нужно было бы каким-то образом сгенерировать этот список лет в SQL... У меня есть этот список лет в памяти, но я не могу выполнять соединения с данными в памяти, не загружая всю свою таблицу в память... Я не могу понять способ получить мой список лет на стороне сервера, чтобы я мог выполнить этот запрос... Однако, как только он появится, я почти уверен, что все, что мне нужно сделать, это какое-то левое внешнее соединение, а затем сгруппировать по годам и выберите сумму... но я не могу туда добраться, пока не найду способ сгенерировать все эти годы.
2 ответа
Я предполагаю, что из вашего тега Linq вы также можете использовать некоторые объекты Linq To Objects. В этом случае вы можете использовать Linq-To-Sql, чтобы получить сводку людей, например
var grouped = (from r in Person
group r by new { r.Start, r.End } into results
select new { results.Key.Start, results.Key.End, count = results.Count()}
).ToList();
Затем переключитесь на объекты Linq To, чтобы найти первый и последний год.
var firstYear = grouped.Min(a=>a.Start) ?? 0;
var lastYear = grouped.Max(a=>a.End) ?? 0;
А затем перебрать все годы, чтобы найти общее количество людей, например, что-то вроде
List<object> yearlySummary = new List<object>();
for (int year = firstYear; year <= lastYear; year++)
{
var no = (from r in grouped where r.Start <= year && r.End >= year select (int?) r.count).Sum() ?? 0;
yearlySummary.Add(new { year, no} );
}
Вы не сможете сделать это в одном запросе, если у вас нет другой таблицы, содержащей годы, которые вы хотите отобразить.
Простое решение (2 запроса + 1 в год)
Один из вариантов — получить минимальные и максимальные даты, используя по 1 запросу, а затем просмотреть даты, чтобы получить информацию, используя 1 запрос в год.
using (var db = new Context())
{
var combinedQuery = db.Dates.Select(d => d.start).Union(db.Dates.Select(d => d.end));
int min = combinedQuery.Min();
int max = combinedQuery.Max();
for (int year = min - 1; year <= max; year++)
{
var count = db.Dates.Count(x => year >= x.start && year <= x.end);
Console.WriteLine("{0}, {1}", year, count);
}
Console.ReadLine();
}
Не так просто (2 запроса)
В качестве альтернативы вы можете получить минимальную и максимальную дату, используя один запрос, воспользовавшись двумя подзапросами.
Теперь, когда у вас есть минимальная и максимальная даты, вы можете просмотреть их, чтобы сгенерировать запрос года (это будет действовать как ваша псевдо-таблица года, которой у вас нет). Это делается путем объединения каждого года вместе, а затем с помощью подвыборки для получения подсчета.
using (var db = new Context())
{
var combinedQuery = db.Dates.Select(d => d.start).Union(db.Dates.Select(d => d.end));
var minAndMax = db.tests.Select(x => new
{
Min = combinedQuery.Min(),
Max = combinedQuery.Max()
}).FirstOrDefault();
int min = minAndMax.Min;
int max = minAndMax.Max;
IQueryable<int> yearQuery = null;
for (int year = min - 1; year <= max; year++)
{
int tempYear = year;
var query = db.tests.Take(1).Select(x => tempYear);
if (yearQuery == null)
{
yearQuery = query;
}
else
{
yearQuery = yearQuery.Concat(query);
}
}
var results = (from year in yearQuery
select new
{
Year = year,
Count = db.Dates.Count(x => year >= x.start && year <= x.end),
}).ToList();
Console.ReadLine();
}
- Обратите внимание, что
linq-to-entities
иlinq-to-sql
действуют немного по-разному, сгенерированные запросы использовалиlinq-to-entities
.
Похожие вопросы
Новые вопросы
sql
Язык структурированных запросов (SQL) - это язык запросов к базам данных. Вопросы должны включать примеры кода, структуру таблицы, примеры данных и тег для используемой реализации СУБД (например, MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 и т. Д.). Если ваш вопрос относится исключительно к конкретной СУБД (использует определенные расширения / функции), используйте вместо этого тег этой СУБД. Ответы на вопросы, помеченные SQL, должны использовать стандарт ISO / IEC SQL.