<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments for MySQL Question of the Day</title>
	<atom:link href="http://mysql-qotd.casperia.net/comments/feed" rel="self" type="application/rss+xml" />
	<link>http://mysql-qotd.casperia.net</link>
	<description>mysql 5.0/5.1 questions for learning purposes</description>
	<lastBuildDate>Fri, 06 Aug 2010 16:56:36 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<item>
		<title>Comment on Question 85: What is the result of the query? by plogi</title>
		<link>http://mysql-qotd.casperia.net/archives/562/comment-page-1#comment-98</link>
		<dc:creator>plogi</dc:creator>
		<pubDate>Fri, 06 Aug 2010 16:56:36 +0000</pubDate>
		<guid isPermaLink="false">http://mysql-qotd.casperia.net/?p=562#comment-98</guid>
		<description>&lt;b&gt;
&lt;small&gt;&lt;pre&gt;
select n,n and 3,n &amp; 3, n mod 4, n and false,n and true 
from (select 0 n union select 1 union select 2 union 
      select 3 union select 4 union select 5 union 
      select 6 union select 7 union select null) v1;

+------+-------+------+-------+-------+-------+
&#124; n    &#124; n and &#124; n &amp;  &#124; n mod &#124; n and &#124; n and &#124;
&#124;      &#124; 3     &#124; 3    &#124; 4     &#124; false &#124; true  &#124;
+------+-------+------+-------+-------+-------+
&#124;    0 &#124;     0 &#124;    0 &#124;     0 &#124;     0 &#124;     0 &#124;
&#124;    1 &#124;     1 &#124;    1 &#124;     1 &#124;     0 &#124;     1 &#124;
&#124;    2 &#124;     1 &#124;    2 &#124;     2 &#124;     0 &#124;     1 &#124;
&#124;    3 &#124;     1 &#124;    3 &#124;     3 &#124;     0 &#124;     1 &#124;
&#124;    4 &#124;     1 &#124;    0 &#124;     0 &#124;     0 &#124;     1 &#124;
&#124;    5 &#124;     1 &#124;    1 &#124;     1 &#124;     0 &#124;     1 &#124;
&#124;    6 &#124;     1 &#124;    2 &#124;     2 &#124;     0 &#124;     1 &#124;
&#124;    7 &#124;     1 &#124;    3 &#124;     3 &#124;     0 &#124;     1 &#124;
&#124; NULL &#124;  NULL &#124; NULL &#124;  NULL &#124;     0 &#124;  NULL &#124;
+------+-------+------+-------+-------+-------+
9 rows in set (0.00 sec)
&lt;/pre&gt;&lt;/small&gt;
And, did you get it right?
&quot;3&quot; is a true value,  that makes &quot;n and true&quot; and &quot;n and 3&quot; the same. The modulo and bit-operations are obvious and so is the fact, that an operation with NULL results in NULL. 
For me the most interesting part is, that TRUE AND NULL is NULL, where as FALSE AND NULL is FALSE.
&lt;/b&gt;</description>
		<content:encoded><![CDATA[<p><b><br />
<small>
<pre>
select n,n and 3,n &#038; 3, n mod 4, n and false,n and true
from (select 0 n union select 1 union select 2 union
      select 3 union select 4 union select 5 union
      select 6 union select 7 union select null) v1;

+------+-------+------+-------+-------+-------+
| n    | n and | n &#038;  | n mod | n and | n and |
|      | 3     | 3    | 4     | false | true  |
+------+-------+------+-------+-------+-------+
|    0 |     0 |    0 |     0 |     0 |     0 |
|    1 |     1 |    1 |     1 |     0 |     1 |
|    2 |     1 |    2 |     2 |     0 |     1 |
|    3 |     1 |    3 |     3 |     0 |     1 |
|    4 |     1 |    0 |     0 |     0 |     1 |
|    5 |     1 |    1 |     1 |     0 |     1 |
|    6 |     1 |    2 |     2 |     0 |     1 |
|    7 |     1 |    3 |     3 |     0 |     1 |
| NULL |  NULL | NULL |  NULL |     0 |  NULL |
+------+-------+------+-------+-------+-------+
9 rows in set (0.00 sec)
</pre>
<p></small><br />
And, did you get it right?<br />
&#8220;3&#8243; is a true value,  that makes &#8220;n and true&#8221; and &#8220;n and 3&#8243; the same. The modulo and bit-operations are obvious and so is the fact, that an operation with NULL results in NULL.<br />
For me the most interesting part is, that TRUE AND NULL is NULL, where as FALSE AND NULL is FALSE.<br />
</b></p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Question 80: How do you read between the rows? by plogi</title>
		<link>http://mysql-qotd.casperia.net/archives/528/comment-page-1#comment-97</link>
		<dc:creator>plogi</dc:creator>
		<pubDate>Thu, 15 Jul 2010 16:25:06 +0000</pubDate>
		<guid isPermaLink="false">http://mysql-qotd.casperia.net/?p=528#comment-97</guid>
		<description>&lt;b&gt;
Aaaaand still a subquery solution:
&lt;pre&gt;
select avg(unix_timestamp(v1.sold_ts)-unix_timestamp(v2.sold_ts)) as avg_diff 
from vending_log v1, vending_log v2 where v2.sold_ts = 
(select sold_ts from vending_log 
  where sold_ts &lt; v1.sold_ts 
  order by 1 desc limit 1 );
&lt;/pre&gt;
&lt;b /&gt;&lt;/pre&gt;&lt;/b&gt;</description>
		<content:encoded><![CDATA[<p><b><br />
Aaaaand still a subquery solution:</p>
<pre>
select avg(unix_timestamp(v1.sold_ts)-unix_timestamp(v2.sold_ts)) as avg_diff
from vending_log v1, vending_log v2 where v2.sold_ts =
(select sold_ts from vending_log
  where sold_ts < v1.sold_ts
  order by 1 desc limit 1 );
</pre>
<p><b /></pre>
<p></b></p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Question 80: How do you read between the rows? by plogi</title>
		<link>http://mysql-qotd.casperia.net/archives/528/comment-page-1#comment-96</link>
		<dc:creator>plogi</dc:creator>
		<pubDate>Thu, 15 Jul 2010 10:39:47 +0000</pubDate>
		<guid isPermaLink="false">http://mysql-qotd.casperia.net/?p=528#comment-96</guid>
		<description>&lt;b&gt;
Here is still a variation on the subquery solution...
Instead of selecting the max(), you can also just select 1 timestamp and limit by 1.
I&#039;m not fond of &quot;limit 1&quot; for anything else than testing/debugging, but in this case it is faster than the &quot;select max()&quot; solution.
&lt;small&gt;&lt;pre&gt;
select avg(vv1.diff) from
  (select *,unix_timestamp(v1.sold_ts) -
            unix_timestamp((select sold_ts
                            from vending_log
                            where sold_ts &lt; v1 .sold_ts order by sold_ts desc limit 1)) as diff
   from vending_log v1) vv1;
&lt;/pre&gt;&lt;/pre&gt;&lt;/small&gt;
&lt;/b&gt;</description>
		<content:encoded><![CDATA[<p><b><br />
Here is still a variation on the subquery solution&#8230;<br />
Instead of selecting the max(), you can also just select 1 timestamp and limit by 1.<br />
I&#8217;m not fond of &#8220;limit 1&#8243; for anything else than testing/debugging, but in this case it is faster than the &#8220;select max()&#8221; solution.<br />
<small>
<pre>
select avg(vv1.diff) from
  (select *,unix_timestamp(v1.sold_ts) -
            unix_timestamp((select sold_ts
                            from vending_log
                            where sold_ts < v1 .sold_ts order by sold_ts desc limit 1)) as diff
   from vending_log v1) vv1;
</pre>
</pre>
<p></small><br />
</b></p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Question 84: Which of the following are equivalent? by plogi</title>
		<link>http://mysql-qotd.casperia.net/archives/541/comment-page-1#comment-95</link>
		<dc:creator>plogi</dc:creator>
		<pubDate>Tue, 13 Jul 2010 17:21:51 +0000</pubDate>
		<guid isPermaLink="false">http://mysql-qotd.casperia.net/?p=541#comment-95</guid>
		<description>&lt;b&gt;
b c 
&lt;/b&gt;</description>
		<content:encoded><![CDATA[<p><b><br />
b c<br />
</b></p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Question 83: How to get the correct price? by plogi</title>
		<link>http://mysql-qotd.casperia.net/archives/537/comment-page-1#comment-94</link>
		<dc:creator>plogi</dc:creator>
		<pubDate>Mon, 12 Jul 2010 18:08:09 +0000</pubDate>
		<guid isPermaLink="false">http://mysql-qotd.casperia.net/?p=537#comment-94</guid>
		<description>&lt;b&gt;
This query left joins the log against the prices using the valid from/to dates.
The left join is there to catch occurences, when there is no price. 

&lt;small&gt;&lt;pre&gt;
select date(v1.sold_ts) as dd,sum(v2.price),count(*),
       sum(if(v2.price is null,1,0)) as prices_missing  
from vending_log v1 left join vending_price v2 on
  (v1.product_id = v2.product_id and 
   date(v1.sold_ts) between v2.valid_from and v2.valid_to)
group by dd;
&lt;/pre&gt;&lt;/small&gt;
&lt;/b&gt;</description>
		<content:encoded><![CDATA[<p><b><br />
This query left joins the log against the prices using the valid from/to dates.<br />
The left join is there to catch occurences, when there is no price. </p>
<p><small>
<pre>
select date(v1.sold_ts) as dd,sum(v2.price),count(*),
       sum(if(v2.price is null,1,0)) as prices_missing
from vending_log v1 left join vending_price v2 on
  (v1.product_id = v2.product_id and
   date(v1.sold_ts) between v2.valid_from and v2.valid_to)
group by dd;
</pre>
<p></small><br />
</b></p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Question 82: More solutions for Q80? by plogi</title>
		<link>http://mysql-qotd.casperia.net/archives/535/comment-page-1#comment-93</link>
		<dc:creator>plogi</dc:creator>
		<pubDate>Sun, 11 Jul 2010 11:56:36 +0000</pubDate>
		<guid isPermaLink="false">http://mysql-qotd.casperia.net/?p=535#comment-93</guid>
		<description>&lt;b&gt;
Yes, another way of solving the problem is using a stored proecedure. There you can use the traditional approach of reading the rows in order and store the previous values in variables.
 
&lt;small&gt;&lt;pre&gt;
drop procedure if exists proc_q80;
delimiter //
CREATE PROCEDURE proc_q80 ()
BEGIN
  declare v_cnt bigint;
  declare v_prev_ts timestamp;
  declare v_ts timestamp;
  declare v_diff bigint;
  declare v_s_diff bigint;
  declare v_done smallint;
  declare c_vendlog CURSOR FOR SELECT sold_ts FROM vending_log order by sold_ts;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = 1;

  OPEN c_vendlog;

  set v_prev_ts = null;
  set v_done = 0;
  set v_cnt = 0;
  set v_s_diff = 0;
  REPEAT
    FETCH c_vendlog INTO v_ts;
    IF v_done = 0 THEN
       set v_diff = unix_timestamp(v_ts) - unix_timestamp(v_prev_ts);
       IF v_diff is not null THEN
          set v_cnt = v_cnt + 1;
          set v_s_diff = v_s_diff + v_diff;
       END IF;
       set v_prev_ts = v_ts;
    END IF;
  UNTIL v_done = 1 END REPEAT;
  close c_vendlog;
  SELECT v_s_diff / v_cnt as avg_diff;
END 
//
delimiter ;
&lt;/pre&gt;&lt;/small&gt;
&lt;/b&gt;</description>
		<content:encoded><![CDATA[<p><b><br />
Yes, another way of solving the problem is using a stored proecedure. There you can use the traditional approach of reading the rows in order and store the previous values in variables.</p>
<p><small>
<pre>
drop procedure if exists proc_q80;
delimiter //
CREATE PROCEDURE proc_q80 ()
BEGIN
  declare v_cnt bigint;
  declare v_prev_ts timestamp;
  declare v_ts timestamp;
  declare v_diff bigint;
  declare v_s_diff bigint;
  declare v_done smallint;
  declare c_vendlog CURSOR FOR SELECT sold_ts FROM vending_log order by sold_ts;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_done = 1;

  OPEN c_vendlog;

  set v_prev_ts = null;
  set v_done = 0;
  set v_cnt = 0;
  set v_s_diff = 0;
  REPEAT
    FETCH c_vendlog INTO v_ts;
    IF v_done = 0 THEN
       set v_diff = unix_timestamp(v_ts) - unix_timestamp(v_prev_ts);
       IF v_diff is not null THEN
          set v_cnt = v_cnt + 1;
          set v_s_diff = v_s_diff + v_diff;
       END IF;
       set v_prev_ts = v_ts;
    END IF;
  UNTIL v_done = 1 END REPEAT;
  close c_vendlog;
  SELECT v_s_diff / v_cnt as avg_diff;
END
//
delimiter ;
</pre>
<p></small><br />
</b></p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Question 81: More solutions for Q80? by plogi</title>
		<link>http://mysql-qotd.casperia.net/archives/533/comment-page-1#comment-92</link>
		<dc:creator>plogi</dc:creator>
		<pubDate>Sat, 10 Jul 2010 18:09:04 +0000</pubDate>
		<guid isPermaLink="false">http://mysql-qotd.casperia.net/?p=533#comment-92</guid>
		<description>&lt;b&gt;
Another solution for Q80 is using a helper table and a join.
The helper table is created with the correct sort order and a surrogate key is added to support the join between the rows.

&lt;small&gt;&lt;pre&gt;
drop table if exists log1;
set @a:=0;
create table log1 
  select @a:=@a+1 as row_id,v1.* 
  from vending_log v1 order by sold_ts;
alter table log1 add primary key(row_id);

select avg(unix_timestamp(v1.sold_ts)-unix_timestamp(v2.sold_ts)) as avg_diff 
from log1 v1, log1 v2 
where v2.row_id=v1.row_id - 1;
&lt;/pre&gt;&lt;/small&gt;&lt;/b&gt;</description>
		<content:encoded><![CDATA[<p><b><br />
Another solution for Q80 is using a helper table and a join.<br />
The helper table is created with the correct sort order and a surrogate key is added to support the join between the rows.</p>
<p><small>
<pre>
drop table if exists log1;
set @a:=0;
create table log1
  select @a:=@a+1 as row_id,v1.*
  from vending_log v1 order by sold_ts;
alter table log1 add primary key(row_id);

select avg(unix_timestamp(v1.sold_ts)-unix_timestamp(v2.sold_ts)) as avg_diff
from log1 v1, log1 v2
where v2.row_id=v1.row_id - 1;
</pre>
<p></small></b></p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Question 80: How do you read between the rows? by plogi</title>
		<link>http://mysql-qotd.casperia.net/archives/528/comment-page-1#comment-91</link>
		<dc:creator>plogi</dc:creator>
		<pubDate>Fri, 09 Jul 2010 21:26:52 +0000</pubDate>
		<guid isPermaLink="false">http://mysql-qotd.casperia.net/?p=528#comment-91</guid>
		<description>&lt;b&gt;
Mysql does not have OLAP extensions or windowing functions at this point. So it is not that easy to refer to the previous row.
Below is one way of solving the problem: With a subquery to retrieve the previous row. It works quite fine and is easy to read, but it is slow.

&lt;small&gt;&lt;pre&gt;
select avg(vv1.diff) from 
  (select *,unix_timestamp(v1.sold_ts) - 
            unix_timestamp((select max(sold_ts) 
                            from vending_log 
                            where sold_ts &lt; v1 .sold_ts)) as diff 
   from vending_log v1) vv1;
&lt;/pre&gt;&lt;/pre&gt;&lt;/small&gt;

The next one is fast, but relies on user variables.

&lt;small&gt;&lt;pre&gt;
set @a:=null;
set @b:=null;
select avg(vv1.diff) from 
  (select @b:=@a,@a:=sold_ts, unix_timestamp(sold_ts) - unix_timestamp(@b) as diff 
   from vending_log order by sold_ts) vv1;
&lt;/pre&gt;&lt;/small&gt;
&lt;/b&gt;</description>
		<content:encoded><![CDATA[<p><b><br />
Mysql does not have OLAP extensions or windowing functions at this point. So it is not that easy to refer to the previous row.<br />
Below is one way of solving the problem: With a subquery to retrieve the previous row. It works quite fine and is easy to read, but it is slow.</p>
<p><small>
<pre>
select avg(vv1.diff) from
  (select *,unix_timestamp(v1.sold_ts) -
            unix_timestamp((select max(sold_ts)
                            from vending_log
                            where sold_ts < v1 .sold_ts)) as diff
   from vending_log v1) vv1;
</pre>
</pre>
<p></small></p>
<p>The next one is fast, but relies on user variables.</p>
<p><small>
<pre>
set @a:=null;
set @b:=null;
select avg(vv1.diff) from
  (select @b:=@a,@a:=sold_ts, unix_timestamp(sold_ts) - unix_timestamp(@b) as diff
   from vending_log order by sold_ts) vv1;
</pre>
<p></small><br />
</b></p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Question 79: Which alternatives exist? by plogi</title>
		<link>http://mysql-qotd.casperia.net/archives/526/comment-page-1#comment-90</link>
		<dc:creator>plogi</dc:creator>
		<pubDate>Thu, 08 Jul 2010 17:31:08 +0000</pubDate>
		<guid isPermaLink="false">http://mysql-qotd.casperia.net/?p=526#comment-90</guid>
		<description>&lt;b&gt;
SQL is very powerful and there are plenty of ways to solve problems.
The example below is only one possibility. It uses a join instead of the &quot;or ... like&quot;.
Instead of the subquery you could use a real table. 
Also there might be inventive ways of using LOCATE, REGEXP/RLIKE...



&lt;small&gt;&lt;pre&gt;
select v1.* from mysql.help_keyword v1,
  (select &#039;%TREE%&#039; as sw union select &#039;%TYPE%&#039;) v2 
where v1.name like v2.sw;

+-----------------+-------+
&#124; help_keyword_id &#124; name  &#124;
+-----------------+-------+
&#124;              87 &#124; RTREE &#124;
&#124;             107 &#124; TYPE  &#124;
&#124;             441 &#124; BTREE &#124;
&#124;             445 &#124; TYPES &#124;
+-----------------+-------+
4 rows in set (0.03 sec)

&lt;/pre&gt;&lt;/small&gt;
&lt;/b&gt;</description>
		<content:encoded><![CDATA[<p><b><br />
SQL is very powerful and there are plenty of ways to solve problems.<br />
The example below is only one possibility. It uses a join instead of the &#8220;or &#8230; like&#8221;.<br />
Instead of the subquery you could use a real table.<br />
Also there might be inventive ways of using LOCATE, REGEXP/RLIKE&#8230;</p>
<p><small>
<pre>
select v1.* from mysql.help_keyword v1,
  (select '%TREE%' as sw union select '%TYPE%') v2
where v1.name like v2.sw;

+-----------------+-------+
| help_keyword_id | name  |
+-----------------+-------+
|              87 | RTREE |
|             107 | TYPE  |
|             441 | BTREE |
|             445 | TYPES |
+-----------------+-------+
4 rows in set (0.03 sec)
</pre>
<p></small><br />
</b></p>
]]></content:encoded>
	</item>
	<item>
		<title>Comment on Question 78: How do you repair this table? by plogi</title>
		<link>http://mysql-qotd.casperia.net/archives/524/comment-page-1#comment-89</link>
		<dc:creator>plogi</dc:creator>
		<pubDate>Wed, 07 Jul 2010 19:11:17 +0000</pubDate>
		<guid isPermaLink="false">http://mysql-qotd.casperia.net/?p=524#comment-89</guid>
		<description>&lt;b&gt;
c

Only the &quot;USE_FRM&quot; option of the REPAIR will help you now.
Use this option only as a last resort.
Afterwards, use &quot;SHOW TABLE STATUS&quot; to check the amount of rows and the auto_increment.
If necessary, adjust the value with &quot;ALTER TABLE t1 AUTO_INCREMENT=&lt;value&gt;&quot;.
As with any REPAIR, make a copy of the table-files first - so that you have something left, in case the REPAIR emtpies your table.
&lt;/value&gt;&lt;/b&gt;</description>
		<content:encoded><![CDATA[<p><b><br />
c</p>
<p>Only the &#8220;USE_FRM&#8221; option of the REPAIR will help you now.<br />
Use this option only as a last resort.<br />
Afterwards, use &#8220;SHOW TABLE STATUS&#8221; to check the amount of rows and the auto_increment.<br />
If necessary, adjust the value with &#8220;ALTER TABLE t1 AUTO_INCREMENT=<value>&#8220;.<br />
As with any REPAIR, make a copy of the table-files first &#8211; so that you have something left, in case the REPAIR emtpies your table.<br />
</value></b></p>
]]></content:encoded>
	</item>
</channel>
</rss>
