Ryšių sukūrimas per ryšio lentelę Python
Tarkime, kad vartotojas buvo įvairiuose miestuose. Šiuo atveju lentelė su vartotojais galėtų turėti tokią formą:
| id | name | city |
|---|---|---|
| 1 | user1 | city1, city2, city3 |
| 2 | user2 | city1, city2 |
| 3 | user3 | city2, city3 |
| 4 | user4 | city1 |
Suprantama, kad tokiu būdu saugoti duomenis neteisinga - miestus reikia išskirti į atskirą lentelę. Štai ji:
| id | name |
|---|---|
| 1 | city1 |
| 2 | city2 |
| 3 | city3 |
Tačiau mums reikia pasidaryti taip, kad kiekvienas vartotojas galėtų nuorodą daryti į kelis miestus. Naudojant dvi lenteles to padaryti negalima.
Mums reikės įvesti vadinamąją ryšio lentelę, kuri susies vartotoją su jo miestais.
Kiekviename šios lentelės įraše bus saugomas ryšys tarp vartotojo ir vieno miesto. Tuo pat metu vienam vartotojui šioje lentelėje bus tiek įrašų, kiek miestų jis lankėsi.
Štai mūsų ryšio lentelė:
| id | user_id | city_id |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 1 |
| 5 | 2 | 2 |
| 6 | 3 | 2 |
| 7 | 3 | 3 |
| 8 | 4 | 1 |
Lentelė su vartotojais saugos tik vartotojų vardus, be ryšių:
| id | name |
|---|---|
| 1 | user1 |
| 2 | user2 |
| 3 | user3 |
| 4 | user4 |
| 5 | user5 |
Užklausos
Padarykime užklausą, kurios pagalba ištrauksime vartotojus kartu su jų miestais. Tam mums reikės padaryti du jungimus: pirmasis jungimas prijungs prie vartotojų ryšio lentelę, o antrasis jungimas per ryšius prijungs miestus:
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
Užklausos rezultatas
Mūsų užklausos rezultatas Python bus turi kiekvieno vartotojo vardą tiek kartų, kiek miestų su juo susieta:
{'user_name': 'user1', 'city_name': 'city1'}
{'user_name': 'user1', 'city_name': 'city2'}
{'user_name': 'user1', 'city_name': 'city3'}
{'user_name': 'user2', 'city_name': 'city1'}
{'user_name': 'user2', 'city_name': 'city2'}
{'user_name': 'user3', 'city_name': 'city2'}
{'user_name': 'user3', 'city_name': 'city3'}
{'user_name': 'user4', 'city_name': 'city1'}
{'user_name': 'user5', 'city_name': None}
Patogiau būtų performatuoti tokį žodyną ir paversti jį šiuo:
{
'user1': ['city1', 'city2', 'city3'],
'user2': ['city1', 'city2'],
'user3': ['city2', 'city3'],
'user4': ['city1'],
'user5': []
}
Parašykime kodą, atliekantį tokią konversiją.
Padarykime tuščią žodyną user_cities_dct,
į kurį palaipsniui suvesime duomenis
apie vartotojus ir miestus, kuriuose jie lankėsi.
Cikle for deklaruojame du kintamuosius
user_name ir city_name, kuriuose
bus saugomas vartotojo vardas ir miesto
pavadinimas. Toliau nurodome sąlygą - jei
vartotojo nėra user_cities_dct, tai jis
pridėsime į šį žodyną kaip raktą.
Taip pat nurodysime sąlygą, kad jei city_name
nėra None, tai jis pridėsime kaip reikšmę
rakto:
result = cursor.fetchall()
user_cities_dct = {}
for row in result:
user_name = row['user_name']
city_name = row['city_name']
if user_name not in user_cities_dct:
user_cities_dct[user_name] = []
if city_name is not None:
user_cities_dct[user_name].append(city_name)
print(user_cities_dct)
Praktinės užduotys
Tarkime, prekė gali priklausyti kelioms kategorijoms. Aprašykite saugojimo struktūrą.
Parašykite užklausą, kuri gaus prekes kartu su jų kategorijomis.
Atspausdinkite gautus duomenis kaip sąrašą
ul taip, kad kiekviename li
pirmiausiai būtų produkto pavadinimas, o po
dvitaskio per kablelį būtų išvardintos
to produkto kategorijos. Maždaug taip:
<ul>
<li>product1: category1, category2, category3</li>
<li>product2: category1, category3</li>
<li>product3: category1</li>
</ul>