Выборка через таблицу связи в C#
Примеры раздела используют SQLite через пакет в файле проекта:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.14" />
</ItemGroup>
</Project>
Запрос, который вытащит юзеров вместе с их городами, делает два соединения: первое присоединит к юзерам таблицу связи, а второе по связям присоединит города:
SELECT
users.name AS user_name, cities.name AS city_name
FROM
users
LEFT JOIN users_cities
ON users_cities.user_id = users.id
LEFT JOIN cities
ON users_cities.city_id = cities.id
Результат запроса
Результат содержит имя каждого юзера столько раз, со сколькими городами он связан - по одной строке на пару юзер-город.
Города одного юзера удобнее собрать в одну строку уже в программе, после выборки. Пример готовит три юзера, три города и пять пар:
using Microsoft.Data.Sqlite;
string dbPath = "lnk_users.db";
if (File.Exists(dbPath))
{
File.Delete(dbPath);
}
using SqliteConnection db = new($"Data Source={dbPath}");
db.Open();
using (SqliteCommand pragma = db.CreateCommand())
{
pragma.CommandText = "PRAGMA foreign_keys = ON";
pragma.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)";
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "CREATE TABLE cities (id INTEGER PRIMARY KEY, name TEXT)";
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "CREATE TABLE users_cities (id INTEGER PRIMARY KEY, user_id INTEGER, city_id INTEGER, FOREIGN KEY (user_id) REFERENCES users (id), FOREIGN KEY (city_id) REFERENCES cities (id))";
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO users (name) VALUES ('user1'), ('user2'), ('user3')";
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO cities (name) VALUES ('city1'), ('city2'), ('city3')";
cmd.ExecuteNonQuery();
}
using (SqliteCommand cmd = db.CreateCommand())
{
cmd.CommandText = "INSERT INTO users_cities (user_id, city_id) VALUES (1,1), (1,2), (2,1), (2,3), (3,2)";
cmd.ExecuteNonQuery();
}
Напишите запрос, который достанет товары вместе с их категориями. Товар может принадлежать нескольким категориям.
Выведите полученные данные в консоль так, чтобы в каждой строке сначала стояло имя продукта, а после двоеточия через запятую перечислялись категории этого продукта:
product1: category1, category2, category3
product2: category1, category3
product3: category1