Newsgroup: it.comp.www.php
Titolo: Select su righe multiple

Scrivo qui, perchè sul NG adatto non mi hanno risposto, magari
qui dentro c'è gente ferrata:
Scusate il title, non saprei come descriverlo altrimenti.
Io ho una tabella così composta:
+--------+---------+--------+
+ userid + chiave  + valore +
+--------+---------+--------+
+ 1      + nome    + mario  +
+ 1      + cognome + rossi  +
+ 2      + nome    + mario  +
+ 2      + cognome + verdi  +
+--------+---------+--------+
Ho la necessità di eseguire dei filtri multipli in base ai
vari record, ovvero, tirar fuori tutti i record
che hanno sia nome = 'mario', sia cognome = 'rossi'
Se faccio
SELECT * FROM tabella WHERE (
    (chiave = 'nome')    AND ('valore' = 'mario')
OR (chiave = 'cognome') AND ('valore' = 'rossi'))
lui mi tira fuori anche l'utente #2 perchè ha "nome" = "mario".
Ovviamente, ho messo un OR ed è giusto che funzioni così.
Va da se che se metto un AND non può funzionare, non ci potrà
mai essere un record che abbia vera sia la condizione "nome" che
"cognome" nello stesso momento (visto che ufficialmente son due
record differenti)
Non posso modificare la struttura della tabella, ed i filtri che
devo fare sono multipli (ho semplificato la mail, ma potrei avere
anche 10-12 filtri, in base ad una intera anagrafica)
Posso, però, creare delle viste, nel caso servisse a qualche cosa.
Avete idea di come posso strutturare una query del genere?
-- 
Non tocca a noi dominare tutte le maree del mondo,
il nostro compito è di fare il possibile per la
salvezza degli anni nei quali viviamo,
sradicando il male dai campi che conosciamo.

On 17 Set, 08:26, Gandalf Corvotempesta

se puoi crearti una vista è meglio.
comunque
select a.nome, b.cognome
  from (select *
             from anagrafica
           where chiave = 'nome') a
          (select *
             from anagrafica
           where chiave = 'cognome') b
   where a.user_id = b.user_id
      and a.nome = 'mario'
      and cognome = 'rossi';
praticamente creo dalla stessa tabella due sottoinsiemi (a, b) ognuno
distinto con solo le caratteristiche che servono (nome, cognome) e le
metto in join per user_id.
Ciao


rettifico.
 select a.valore as nome, b.valore as cognome
   from (select *
              from anagrafica
            where chiave = 'nome') a
           (select *
              from anagrafica
            where chiave = 'cognome') b
    where a.userid = b.userid
       and a.valore = 'mario'
       and b.valore = 'rossi';

        and b.valore = 'rossi';
Si, volendo posso creare la vista, ma c'è un problema,
sia con la vista che con la tua query:
i filtri sono multipli e dinamici in base alle
richieste utente.
un utente potrebbe fare la ricerca di nome e cognome
mentre un altro di cognome e città, oppure un altro
ancora indirizzo e regione
con la tua query, dovrei fare i campi fissi.
Posso generare dinamicamente le sotto-select, ma non
avrei idea (senza impazzire) di come gestire gli alias.

On 17 Set, 20:05, Gandalf Corvotempesta

ti suggerivo la vista proprio per non mettere i campi di where
condition fissi.
una volta che crei la vista, le select le fai secche sulla vista.
riprendendo la select
CREATE VIEW tabella_normalizzata AS
  select a.chiave as chiave, a.valore as nome, b.valore as cognome,
c.valore as citta, d.valore as indirizzo
    from (select *
               from anagrafica
             where chiave = 'nome') a
            (select *
               from anagrafica
             where chiave = 'cognome') b,
            (select *
               from anagrafica
             where chiave = 'citta') c
            (select *
               from anagrafica
             where chiave = 'indirizzo') c
     where a.userid = b.userid
        and c.userid = a.userid
        and d.userid = a.userid;
e andando avanti aggiungendo i vari valori/chiavi che ti interessano,
creando una vista del genere
avrai normalizzato la tua tabella che sarà cosi composta:
*----------*----------------*--------------*-----------*---------------
*-------------*
* chiave *   nome        * cognome   * citta     * indirizzo    *
ecc        *
*----------*---------------*---------------*-----------*---------------
*-------------
*    1      *   mario        * rossi         * roma     * tal dei tali
* ecc         *
*    2      *   mario        * verdi         * milano  * pinco pallo*
ecc         *
*    3       *  napoleone * bonaparte * milano   * pinco pinco *
ecc        *
-----------------------------------------------------------------------------------
a questo punto devi solo fare una query sulla tua vista come più ti
piace e con tutti i filtri che vuoi.
 select * from tabella_normalizzata where citta = 'milano' and nome =
'mario'
 select * from tabella_normalizzata where cognome = 'bonaparte'
ecc...
i filtri li puoi tranquillamente generare in modo dinamico, in php o
in un qualsiasi liguaggio
<?php
$sqlstringa = "select * from tabella_normalizzata';
$conta_condition = 0;
if($cognome <> '')
{
   if ($conta_condition == 0 ) {
    $conta_condition = $conta_condition +1;
    $sqlstringa =  $sqlstringa . ' where cognome = ' . $cognome;
} else
{
   $conta_condition = $conta_condition +1;
   $sqlstringa =  $sqlstringa . ' and cognome = ' . $cognome;
}
}
ecc ...
?>
dopo aver sanitizzato le variabili ($cognome ecc)
Ciao

 e andando avanti aggiungendo i vari valori/chiavi che ti interessano,
Forse mi sono espresso male.
I campi sono dinamici, li crea l'utente.
io non ho idea che un campo sia "nome" e l'altro "cognome"
la tabella indicata viene popolata dagli utenti, ciascuno dei
quali può creare illimitati campi, quindi non posso fare come
dici te e creare staticamente la view con l'elenco statico
dei campi, perchè i campi non sono statici ma dinamici.

On 17 Set, 21:02, Gandalf Corvotempesta

potresti risolvere in modo un pò arzigogolato, facendo una select
distinct sul campo "chiave" e utilizzando il risultato per crearti la
view in modo dinamico.
certo non è banale ma fattibile.
altra soluzione è quella di creare un loop per ogni filtro.
prima estrai tutti quelli che hanno una certa condizione e poi sul
risultati di questi applichi un secondo filtro, e poi con il risultato
il terzo filtro e così via.
altre soluzioni non me ne vengono in mente
indubbiamente la tabella di origine non è ottimizzata per questo tipo
di scopo.
in genere tabelle del genere non vengono consigliate.
Ciao

 in genere tabelle del genere non vengono consigliate.
Lo so, ma purtroppo non l'ho fatta io e non posso cambiare la
tabella senza cambiare anche un buon 3/4 di software, visto che
tutto il motore delle ricerche ruota li attorno.
un conto è creare una vista, un conto è ristrutturare tutto.

 un conto è creare una vista, un conto è ristrutturare tutto.
ma no avevi detto che i possibili campi chiave erano 10/12
(ho semplificato la mail, ma potrei avere
anche 10-12 filtri, in base ad una intera anagrafica), quindi in
qualche modo i campi "chiave" sono "finiti".
Ciao