Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > it.comp.www.php > #22644 > unrolled thread

[OT] MySQL/MariaDB db per gusti utenti

Started by^Bart <gabriele1NOSPAM@hotmail.com>
First post2019-04-21 19:32 +0200
Last post2019-04-22 19:13 +0200
Articles 5 — 2 participants

Back to article view | Back to it.comp.www.php


Contents

  [OT] MySQL/MariaDB db per gusti utenti ^Bart <gabriele1NOSPAM@hotmail.com> - 2019-04-21 19:32 +0200
    Re: [OT] MySQL/MariaDB db per gusti utenti Alessandro Pellizzari <shuriken@amiran.it> - 2019-04-22 10:37 +0100
      Re: [OT] MySQL/MariaDB db per gusti utenti ^Bart <gabriele1NOSPAM@hotmail.com> - 2019-04-22 18:01 +0200
        Re: [OT] MySQL/MariaDB db per gusti utenti Alessandro Pellizzari <shuriken@amiran.it> - 2019-04-22 17:23 +0100
          Re: [OT] MySQL/MariaDB db per gusti utenti ^Bart <gabriele1NOSPAM@hotmail.com> - 2019-04-22 19:13 +0200

#22644 — [OT] MySQL/MariaDB db per gusti utenti

From^Bart <gabriele1NOSPAM@hotmail.com>
Date2019-04-21 19:32 +0200
Subject[OT] MySQL/MariaDB db per gusti utenti
Message-ID<q9i9g9$1i7b$1@gioia.aioe.org>
Salve,

dovrei creare un db per raccogliere i gusti degli utenti, nello 
specifico mi trovo in questa situazione:

CREATE TABLE foodstyles
(
id_foodstyle BIGINT(7) NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL UNIQUE,
FK_id_ingredient SMALLINT(7) NOT NULL,
PRIMARY KEY (id_foodstyle),
INDEX (FK_id_ingredient),
FOREIGN KEY (FK_id_ingredient) REFERENCES ingredients (id_ingredient)
)
ENGINE=INNODB;

In questo caso dovrei ripetere vegan tutte le volte necessarie a 
raccogliere tutti gli ingredienti che formano il gruppo vegan:

name   | FK_id_ingredient
vegan  |       4
vegan  |       2
vegan  |       8
vegan  |       9
vegan  |       3

A questo punto converrebbe gli ingredienti metterli tutti nello stesso 
campo evitando quindi la FK?

Ho pensato anche di creare una tabella con tutti gli stili quindi vegan, 
vegetarian ed avere una tabella tipo:

FK_food   | FK_id_ingredient
1         |       4
1         |       2
1         |       8
1         |       9
1         |       3

Ma credo cambi poco...

Saluti!
^Bart

[toc] | [next] | [standalone]


#22645

FromAlessandro Pellizzari <shuriken@amiran.it>
Date2019-04-22 10:37 +0100
Message-ID<gi5gahF2ut7U1@mid.individual.net>
In reply to#22644
On 21/04/2019 18:32, ^Bart wrote:

> A questo punto converrebbe gli ingredienti metterli tutti nello stesso 
> campo evitando quindi la FK?

In SQL hai relativamente poca scelta, una volta che decidi di
normalizzare i DB.

1:1 -> Metti tutto nella stessa tabella

1:n -> Hai una tabella con gli "1", e una tabella con gli "n".

n:m -> Hai 3 tabelle: una con gli "n", una con gli "m" e una con solo
due colonne: fk_n e fk_m

Nel tuo caso hai una relazione n:m
Un ingrediente può appartenere a diversi stili.
Per esempio, il latte è vegetariano e onnivoro, ma non vegano, mentre il
radicchio appartiene a tutti e tre, ma non al carnivoro.

Quindi la soluzione è una tabella con gli stili, una con gli ingredienti
e una tabella di link:

create table foodstyle (
  id int not null auto_increment primary key,
  name varchar(255)
)

create table ingredient (
  id int not null auto_increment primary key,
  name varchar(255),
)

create table foodstyle_ingredient (
  foodstyle int not null,
  ingredient int not null,
  foreign key fk_foodstyle(foodstyle) references foodstyle (id),
  foreign key fk_ingredient(ingredient) references ingredient (id)
)

Quindi la tua seconda soluzione è quella giusta.

Bye.

[toc] | [prev] | [next] | [standalone]


#22646

From^Bart <gabriele1NOSPAM@hotmail.com>
Date2019-04-22 18:01 +0200
Message-ID<q9kohh$3g1$1@gioia.aioe.org>
In reply to#22645
> In SQL hai relativamente poca scelta, una volta che decidi di
> normalizzare i DB.

Per ora ho studiato solo SQL, ho presente l'esistenza di altre 
tecnologie di cui però non conosco le caratteristiche, in base alla tua 
esperienza vi sarebbe ipoteticamente un'altra soluzione con un'altra 
tecnologia?

> Quindi la tua seconda soluzione è quella giusta.

E' sembrata anche a me la più "sensata" ed ho ragionato con la logica 
negativa (più sicura quando si parla di intolleranze) ovvero mettere 
nella tabella tutto ciò che è vietato stessa situazione per lo style.

Ora ho un ultimo dubbio sulle traduzioni, ho una main table degli 
ingredients in inglese ed una ingredient_langs con tutte le traduzioni 
collegata ad ogni id della tabella ingredients.

Ovviamente se ho un utente italiano leggerà dall'ingredient_langs gli id 
corrispondenti all'italiano ma un utente inglese dovrebbe leggere sempre 
dalla tabella ingredient_langs ma in realtà gli ingredienti con la sua 
lingua sono in ingredients!

Morale della favola potrei copiare tutti gli ingredienti in inglese 
contenuti in ingredients pari pari in ingredient_lang ed assegnargli un 
id associato alla lingua inglese, non vedo altre soluzioni, di seguito 
un esempio:

ingredients
-------------------
id      |    name
-------------------
1	|    milk
2	|    spelt
3	|    onion

languages
-------------------
id	|    name
-------------------
1	|    english
2	|    spanish
3	|    italian

ingredient_langs
----------------------------------------------------------
id	|     name	|FK_id_languages|FK_id_ingredients
----------------------------------------------------------
1	|     Latte	|       3	|	1
2	|     Farro     |       3	|	2
3	|     Cipolla	|       3	|	3
4	|     Leche	|       2	|	1
5	|     Farro	|       2	|	2
6	|     Cebolla	|       2	|	3

users
------------------------------------------------------------
id	|    name    |FK_id_languages|FK_ingredient_langs
------------------------------------------------------------
1	|    John	|	1	|	?
2	|    Paolo	|	3	|	1
3	|    Paolo	|	3	|	2
4	|    Paolo	|	3	|	3
5	|    Firmin	|	2	|	4
6	|    Firmin	|	2	|	5
7	|    Firmin	|	2	|	6

Ovviamente ho anche una tabella più specifica per gli users questa è 
solo di esempio per far capire il problema legato alla lingua inglese.

> Bye.

Saluti e grazie per la risposta! :)
^Bart

[toc] | [prev] | [next] | [standalone]


#22647

FromAlessandro Pellizzari <shuriken@amiran.it>
Date2019-04-22 17:23 +0100
Message-ID<gi683eF802jU1@mid.individual.net>
In reply to#22646
On 22/04/2019 17:01, ^Bart wrote:

>> In SQL hai relativamente poca scelta, una volta che decidi di
>> normalizzare i DB.
> 
> Per ora ho studiato solo SQL, ho presente l'esistenza di altre 
> tecnologie di cui però non conosco le caratteristiche, in base alla tua 
> esperienza vi sarebbe ipoteticamente un'altra soluzione con un'altra 
> tecnologia?

Ogni tecnologia ha i suoi pro e i suoi contro, e la stessa cosa può
venire implementata con diversi tipi di DB con pro e contro.

Bisognerebbe conoscere tutte le specifiche richieste dall'applicazione
per consigliare qualcosa di specifico.

La cosa migliore è sempre astrarre lo storage dalla logica
dell'applicazione, e personalmente ho trovato che usare GraphQL a
livello API porta a pensare a modi più astratti di strutturare il DB e
renderlo indipendente, ma per ora ti consiglio di concentrarti su SQL e
non pensarci troppo.

> Ora ho un ultimo dubbio sulle traduzioni, ho una main table degli 
> ingredients in inglese ed una ingredient_langs con tutte le traduzioni 
> collegata ad ogni id della tabella ingredients.

Io lo farei in modo leggermente diverso: una singola tabella per gli
ingredienti, con una chiave primaria su due colonne:

create table languages (
  id primary key -- bla bla bla la roba di MySQL
  name varchar(255)
)

create table ingredients (
  id int, -- NB: no primary key
  lang int,
  name
  foreign key fk_lang(lang) references languages(id),
  primary key (id, lang)
)

Hai la rogna di dover generare a mano un nuovo "id" quando crei un nuovo
ingrediente, ma la tabella diventa qualcosa tipo:

--------------------------------
id	|     name	| lang |
--------------------------------
1	|     Latte	|   3  |
2	|     Farro     |   3  |
3	|     Cipolla	|   3  |
1	|     Leche	|   2  |
2	|     Farro	|   2  |
3	|     Cebolla	|   2  |

Quindi il latte avrà sempre id 1 in tutte le lingue, e costruire le
query sarà più semplice, oltre a non dover avere un'asplosione algebrica
di righe nella tabella users (ricorda che è n:m, quindi ti serve una
tabella di collegamento):

create table users(
  id primary key,
  name varchar(255)
)

create table user_ingredients (
  user int,
  ingredient int,
  foreign key fk_user(user) references users(id),
  foreign key fk_ingredient(ingredient) references ingredients(id)
)

Per esempio, volendo prendere gli ingredienti dell'utente 5 in spagnolo
(lang 2):

select u.id, u.name, i.name
from
  users u
left join user_ingredients ui
  on ui.user = user.id
left join ingredients i
  on i.id = ui.ingredient
  and i.lang = 2
where
  u.id = 5

O qualcosa del genere (non l'ho testata)

Bye.

[toc] | [prev] | [next] | [standalone]


#22648

From^Bart <gabriele1NOSPAM@hotmail.com>
Date2019-04-22 19:13 +0200
Message-ID<q9ksng$ml3$1@gioia.aioe.org>
In reply to#22647
> renderlo indipendente, ma per ora ti consiglio di concentrarti su SQL e
> non pensarci troppo.

Credo anch'io sia la soluzione migliore!

> create table ingredients (
>    id int, -- NB: no primary key
>    lang int,
>    name
>    foreign key fk_lang(lang) references languages(id),
>    primary key (id, lang)
> )
> 
> Hai la rogna di dover generare a mano un nuovo "id" quando crei un nuovo
> ingrediente, ma la tabella diventa qualcosa tipo:

Ho capito il tipo di rogna... diciamo che basterebbe fare 
"semplicemente" attenzione durante l'inserimento dei dati attenzione che 
bisognerebbe porre anche se il collegamento fosse stato legato con una FK!

Però quando si dovessero aggiungere almeno una decina di lingue volendo 
scegliere quella inglese come quella principale dovrei fare un filtro 
specifico per tirarmi fuori tutti gli id ed associarli alle nuove lingue.

> Quindi il latte avrà sempre id 1 in tutte le lingue, e costruire le
> query sarà più semplice, oltre a non dover avere un'asplosione algebrica
> di righe nella tabella users (ricorda che è n:m, quindi ti serve una
> tabella di collegamento):

Chiarissimo, da un'altra parte mi hanno suggerito, credo, la stessa 
cosa; nell'esempio citato c'è un ingrediente milk che esiste in entrambe 
le lingue mentre chi mi ha risposto ha supposto che ci potessero essere 
due ingredienti senza traduzione in inglese come boter (butter) e eieren 
(eggs).

Add a language_id to every table that has descriptions

so for Inredients:
ingredients
-------------------
id | language | name
-------------------
1  |   0      | milk
2  |   0      | spelt
3  |   0      | onion

Also define a 'default' language (i did choose to make '0' the default 
language)

Other languages can be added (i.e. 1='Dutch')
1  |   1      | melk
4  |   1      | boter
5  |   1      | eieren

This can, of course, be 'beautified' with a foreign key, so you can only 
create a dutch translation for an ingredient which has an English text.


    SELECT ingredient.name
    from ingredients, users
    where id=3 and language_id = users.language_id
    order by language_id desc
    limit 1

This should give description in language of user, and when the 
description in the language of the user does not exist it will show the 
default ('0') description.

> Bye.

Saluti.
^Bart

[toc] | [prev] | [standalone]


Back to top | Article view | it.comp.www.php


csiph-web