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