Esercizio sql

891

Nuovo Utente
77
7
Ciao a tutti. Ho un dubbio che non so se possa essere risolto in maniera ''elementare'' o meno. Facendola breve, ho creato la tabella "persona" e la tabella "amico" in questo modo (metto solo le chiavi)
Codice:
PERSONA                    AMICO

id                        id1
                          id2

pk(id)                   pk(id1,id2)


Dove id1 e id2 sono chiavi esterne di persona(id). La relazione dovrebbe essere simmetrica, quindi la chiave (id1,id2) e la chiave (id2,id1) dovrebero far riferimento alla stessa riga. Come posso fare per rendere la relazione simmetrica? Grazie
 

Eduadie

Utente Attivo
204
24
Se in AMICO immagino che gli id PERSONA li memorizzi in due colonne differenti ti basta una clausola WHERE.
SQL:
SELECT * FROM AMICO
WHERE COLONNA1 = 'id1' OR COLONNA2 = 'id1'
 

891

Nuovo Utente
77
7
Se in AMICO immagino che gli id PERSONA li memorizzi in due colonne differenti ti basta una clausola WHERE.
SQL:
SELECT * FROM AMICO
WHERE COLONNA1 = 'id1' OR COLONNA2 = 'id1'
No ma intendo, è possibile creare dei vincoli all'interno della tabella per far si che questo controllo venga creato in automatico? Con le interrogazioni saprei come fare.
Mi spiego meglio. Oltre alla tabella AMICO c'è anche la tabella PIACE, la quale comprende sempre id1 e id2 come chiavi primaria ma non è simmetrica, quindi effettivamente le coppie (id1,id2) e (id2,id1) fanno riferimento a due record distinti, cosa che nella tabella AMICO non è vera perchè si tratta di relazione simmetrica. Ora, le due relazioni sono una simmetrica (AMICO) e una asimmetrica(PIACE) e la mia domanda è, a livello di tabelle, sono entrambe uguali?
Spero di essermi spiegato. Grazie intento!
 

Eduadie

Utente Attivo
204
24
Ti riesco a seguire a tratti. Che intendi per tabelle uguali? Se tu le interroghi per azioni differenti è ovvio che magari possano servirti entrambe anche se memorizzano quasi gli stessi dati (magari puoi migliorarla progettando la base di dati in modo diverso). Se tu la tabella AMICO la usi per tenere conto delle amicizie di una persona mentre PIACE per tener conto dei "mi piace" essendo relazioni lo stesso 1 ad 1 è ovvio che si creano associazioni identiche in entrambe le tabelle.
Spero di essere stato chiaro e aver in parte capito quello che intendi :D
 
  • Mi piace
Reazioni: 891

1nd33d

Utente Attivo
653
279
CPU
Intel i5 3570K @ 4,5Ghz
Dissipatore
Scythe Mugen 2
Scheda Madre
Gigabyte Z77X-UD3H
HDD
Samsung 840 PRO 256GB + Sandisk Ultra 250GB + Sandisk Plus 960GB
RAM
2x8GB Crucial Ballistix Tactical @2000Mhz CL9
GPU
XFX RX480 GTR Black Edition
Audio
Auzentech X-Fi Forte
Monitor
AOC i2369VW
PSU
Seasonic P660
Case
eh?
Periferiche
Razer Naga HEX v2
OS
Windows 10 64bit - Linux Mint 18
La relazione dovrebbe essere simmetrica, quindi la chiave (id1,id2) e la chiave (id2,id1) dovrebero far riferimento alla stessa riga. Come posso fare per rendere la relazione simmetrica? Grazie
Se ho ben capito, tu vuoi che, nel caso in cui nella tabella ci sia la chiave (id1, id2), non possa essere presente anche la chiave (id2, id1) e viceversa.
In tal caso penso che dovresti usare un trigger.
 
  • Mi piace
Reazioni: 891

891

Nuovo Utente
77
7
Se tu la tabella AMICO la usi per tenere conto delle amicizie di una persona mentre PIACE per tener conto dei "mi piace" essendo relazioni lo stesso 1 ad 1 è ovvio che si creano associazioni identiche in entrambe le tabelle.
Spero di essere stato chiaro e aver in parte capito quello che intendi :D
Ok quindi le tabelle sono uguali poichè contengono gli stessi dati e poi io con le interrogazioni tiro fuori quello che mi serve, mi pare di avere capito giusto, no?

Se ho ben capito, tu vuoi che, nel caso in cui nella tabella ci sia la chiave (id1, id2), non possa essere presente anche la chiave (id2, id1) e viceversa.
In tal caso penso che dovresti usare un trigger.

Esatto, questa potrebbe essere la soluzione! Mi proverò a informare meglio comunque visto che i trigger ancora non li abbiamo fatti penso che basti eliminare i doppioni tramite interrogazioni. Comunque grazie, eventualmente scriverò qui sotto se dovessi avere bisogno di aiuto sui trigger :ok:
 
  • Mi piace
Reazioni: Eduadie

Eduadie

Utente Attivo
204
24
Ok quindi le tabelle sono uguali poichè contengono gli stessi dati e poi io con le interrogazioni tiro fuori quello che mi serve, mi pare di avere capito giusto, no?
Esattamente. Ovviamente se tu non vuoi creare stesse righe in una tabella puoi intervenire o come ti è stato suggerito con i trigger (controllando quindi con l'SQL direttamente) altrimenti a seconda del linguaggio che usi puoi implementare controlli lato codice.
 

IlPunto

Nuovo Utente
9
6
Mi vengono in mente 4 soluzioni:
- TRIGGER: come detto da altri utenti qui sopra. Lo svantaggio di questa soluzione è che il trigger scatta ogni volta che provi a fare una INSERT e dovendo controllare se sulla tabelle esiste già una relazione "simile" deve pure fare una query. In uno scenario critico per le performance potrebbe essere un problema.
- CONSTRAINT: stesso problema dei TRIGGER. Inoltre quando il constraint fallisce lancia un errore che poi deve essere gestito applicativamente. Userei questa soluzione in combinazione solo con la soluzione successiva.
- GESTIONE LATO SOFTWARE: gestisci questa tematica lato software, nella pratica però finisce per fare sempre quello che fa il TRIGGER, ovvero con una query controlli e poi decidi cosa fare.
- ACCETTARE I DUPLICATI: io valuterei attentamente questa soluzione perché la seguente query pur sintatticamente e funzionalmente corretta non è efficiente sui grandi numeri.

SQL:
SELECT * FROM AMICO
WHERE COLONNA1 = 'id1' OR COLONNA2 = 'id1'

Le query con con un OR tendezialmente non lo sono.
Ovviamente questa soluzione ha senso solo se la tabella AMICO ha solamente i 2 campi chiave. Se ci fossero anche altri campi da duplicare, diventerebbe insostenibile e poco mantenibile.

Sulle prime 3 soluzioni aggiungo un ulteriore consiglio: se proprio vuoi mantenere una sola relazione, dati una regola su quale tenere. Per esempio: salva solo la relazione con id1 < id2. In questo modo, se dovessi verificare se 2 persone sono amiche invece di scrivere:

SQL:
SELECT * FROM AMICO
WHERE (COLONNA1 = 'id1' AND COLONNA2 = 'id2') OR
(COLONNA1 = 'id2' AND COLONNA2 = 'id1')

potresti farlo molto più semplicemente con:

SQL:
SELECT * FROM AMICO
WHERE COLONNA1 = 'id1' AND COLONNA2 = 'id2'
 

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!