did'n arrive. re-submitted  -- sorry
Selon [EMAIL PROTECTED]:

> Hi,
> If we forget the first method which i mis-adviced, i can give a third which
> is
> generic.
>
> suppose that you have an indexed "type" column on each table (what i did).
> You
> can work with 3 variables. If they are different, you query for a join, if
> they
> are equal, you transform the join to a simple query.
> The only condition is to add a where clause a the column "type" which will
> retreive empty set for the non selected conditions.
>
> Example :!
>
> set @cat1:='news'; set @cat2:='faq'; set @cat3:='forum';
>
> mysql> select id,@cat1 as selected, type from news where [EMAIL PROTECTED]
>     ->      union select id,@cat2 as selected, type from faq where [EMAIL 
> PROTECTED]
>     ->     union select id,@cat3 as selected, type from forum where
> [EMAIL PROTECTED];
> +------+----------+-------+
> | id   | selected | type  |
> +------+----------+-------+
> |    1 | news     | news  |
> |    2 | faq      | faq   |
> |    3 | forum    | forum |
> +------+----------+-------+
> 3 rows in set (0.00 sec)
>
>
> When you have only one value, the same query gives :
> ****************************************************
>
>
> mysql> set @cat1='news'; set @cat2='news'; set @cat3='news';
> Query OK, 0 rows affected (0.00 sec)
>
> here the 3 variables are the same, so 2 queries will find an empty set.
>
> mysql> select id,@cat1 as selected, type from news where [EMAIL PROTECTED]
>     ->      union select id,@cat2 as selected, type from faq where [EMAIL 
> PROTECTED]
>     ->     union select id,@cat3 as selected, type from forum where
> [EMAIL PROTECTED];
> +------+----------+------+
> | id   | selected | type |
> +------+----------+------+
> |    1 | news     | news |
> +------+----------+------+
> 1 row in set (0.00 sec)
>
> performance will not be affected since the index will be used for non used
> tables.
>
> Hope that helps :o)
>
> Mathias
>
>
>
> Selon Sebastian <[EMAIL PROTECTED]>:
>
> > Michael Stassen wrote:
> >
> > > [EMAIL PROTECTED] wrote:
> > >
> > >> Hi Sebastian;
> > >> There is always crazy things somewhere.
> > >> I'll give you two methods for that :
> > >>
> > >> mysql> select id,'news' as selected, type from news
> > >>     -> union select id,'faq' as selected, type from faq
> > >>     -> union select id,'forum' as selected, type from forum;
> > >> +------+----------+-------+
> > >> | id   | selected | type  |
> > >> +------+----------+-------+
> > >> |    1 | news     | news  |
> > >> |    2 | faq      | faq   |
> > >> |    3 | forum    | forum |
> > >> +------+----------+-------+
> > >> 3 rows in set (0.00 sec)
> > >>
> > >>
> > >> FIRST CRAZY METHOD :
> > >> *************************
> > >> mysql> set @cat='news';
> > >> Query OK, 0 rows affected (0.00 sec)
> > >>
> > >> mysql> select * from (
> > >>     -> select id,'news' as selected, type from news
> > >>     -> union select id,'faq' as selected, type from faq
> > >>     -> union select id,'forum' as selected, type from forum
> > >>     -> ) Temp
> > >>     -> where [EMAIL PROTECTED];
> > >> +------+----------+------+
> > >> | id   | selected | type |
> > >> +------+----------+------+
> > >> |    1 | news     | news |
> > >> +------+----------+------+
> > >> 1 row in set (0.00 sec)
> > >>
> > >>
> > >> SECOND CRAZY METHOD (I prefer):
> > >> *************************
> > >>
> > >> set @cat := 'news';
> > >> set @sql:=concat('select id,','''',@cat,'''',' as selected from ',@cat);
> > >> select @sql;
> > >> prepare stmt from @sql ;
> > >> execute stmt;
> > >>
> > >> +------+----------+
> > >> | id   | selected |
> > >> +------+----------+
> > >> |    1 | news     |
> > >> +------+----------+
> > >> 1 row in set (0.00 sec)
> > >>
> > >> deallocate prepare stmt;
> > >>
> > >>
> > >> ********* another click with ?cat=faq
> > >>
> > >> set @cat := 'faq';
> > >> set @sql:=concat('select id,','''',@cat,'''',' as selected from ',@cat);
> > >> select @sql;
> > >> prepare stmt from @sql ;
> > >> execute stmt;
> > >>
> > >> mysql> execute stmt;
> > >> +------+----------+
> > >> | id   | selected |
> > >> +------+----------+
> > >> |    2 | faq      |
> > >> +------+----------+
> > >> 1 row in set (0.00 sec)
> > >>
> > >> deallocate prepare stmt;
> > >>
> > >> OTHER CRAZY METHODS - coming emails :o)
> > >> --------------------
> > >>
> > >> A+
> > >> Mathias
> > >
> > >
> > > The first method is horribly inefficient (and requires mysql 4.1+).
> > > It reads all 3 tables, unions the resulting rows, checks for (and
> > > removes) duplicate rows, then finally throws away roughly 2/3 of the
> > > results (the rows from the 2 unwanted tables.  Compare that to the
> > > simple query which only addresses the 1 desired table.  Mathias is
> > > aware of this, which is why he gives the second method.  It creates
> > > the simple, one-table query using the value of $cat to choose which
> > > table.
> > >
> > > The big problem here is that neither of these methods actually do what
> > > you asked for.  That is, neither works if $cat is not set.  With both
> > > methods, you will get no rows unless $cat is set.  In fact, the second
> > > method will give a syntax eror, as there will be no table name in the
> > > FROM clause.
> > >
> > > Now, I never said this couldn't be done in SQL.  Assuming $cat is
> > > already set, the statement in $sql below should do what you asked for:
> > >
> > >   $sql = "SELECT id, 'news' AS type, .... FROM news
> > >           WHERE ($cat = '' OR $cat = 'news')
> > >         UNION
> > >           SELECT id, 'faq' AS type, .... FROM faq
> > >           WHERE ($cat = '' OR $cat = 'faq')
> > >         UNION
> > >           SELECT id, 'forum' AS type, .... FROM forum
> > >           WHERE ($cat = '' OR $cat = 'forum')"
> > >
> > > MySQL's optimizer should be smart enough to notice that if $cat is
> > > set, 2 of the 3 unioned queries will have impossible WHERE clauses, so
> > > those queries will be skipped, making this relatively efficient.
> > >
> > > Even though this works, though, I think it's a bit of a hack.  It's
> > > clever SQL which allows two separate queries to masquerade as one,
> > > based on the value of $cat.  I really think the simple, separate query
> > > solution I sent in my previous message
> > >
> > >   if ($cat == 'news' or $cat == 'faq' or $cat == 'forum')
> > >   {
> > >     $sql = "SELECT id, '$cat' AS type, ... FROM $cat";
> > >   }
> > >   else
> > >   {
> > >     $sql = " SELECT id, 'news' AS type, .... FROM news
> > >             UNION
> > >              SELECT id, 'faq' AS type, .... FROM faq
> > >             UNION
> > >              SELECT id, 'forum' AS type, .... FROM forum";
> > >   }
> > >
> > > is better, as it is clearer what we are doing (one query if we know
> > > the table, three queries unioned if we don't), so it should be easier
> > > to understand and maintain down the road (by you or the next guy).
> > >
> > > Michael
> >
> > you just gave me an idea.. maybe this is better:
> >
> > SET @cat = '$cat';
> >
> > SELECT id,  'news' AS type,
> > WHERE [expression...] AND (@cat = 'news' OR @cat = '')
> >
> > UNION
> >    SELECT id,  'faq' AS type,
> >    WHERE [expression...] AND (@cat = 'faq' OR @cat = '')
> >
> > UNION
> >   [SELECT ........]
> >
> > works regardless if $cat is set or not.
> >
> >
>
>
>



-- 
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to