On Sat, Jul 19, 2008 at 4:18 AM, Rob Wultsch <[EMAIL PROTECTED]> wrote:
> On Fri, Jul 18, 2008 at 3:46 PM, Rob Wultsch <[EMAIL PROTECTED]> wrote:
>> I'm sure there is a way to write this in a single query, but I bet it
>> it is ugly as heck, probably with a bunch of derived tables.
>
> INSERT INTO balances (userid, points)
> SELECT users.userid, users.points
> FROM users
> LEFT JOIN (
>        SELECT userid, MAX(timestamp_dump) AS 'timestamp_dump'
>        FROM balances
>        GROUP BY userid
>        ) AS b1 USING(userid)
> LEFT JOIN balances b2 USING(userid,timestamp_dump)
> WHERE users.points != b2.points
>        OR b2.points IS NULL ;
>
> This query is a dog, That stored procedure is pretty horrible. I'm
> going to play with trying to figure out how to optimize this. Fun
> stuff.
>
>
> --
> Rob Wultsch
>

Unless I am missing something Postgres is 100X faster for the query shown above.

Awesome...

postgres=# DROP TABLE IF EXISTS users, balances;
DROP TABLE
postgres=# CREATE TABLE users(
postgres(# userid SERIAL,
postgres(# points INT);
NOTICE:  CREATE TABLE will create implicit sequence "users_userid_seq" for seria
l column "users.userid"
CREATE TABLE
postgres=# CREATE TABLE balances(
postgres(# userid INT,
postgres(# points INT,
postgres(# timestamp_dump TIMESTAMP DEFAULT NOW(),
postgres(# PRIMARY KEY(userid,timestamp_dump) );
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "balances_pkey" f
or table "balances"
CREATE TABLE
postgres=# INSERT INTO users(points)
postgres-# SELECT random()*100 FROM generate_series(0,10000) ;
INSERT 0 10001
postgres=# INSERT INTO balances (userid, points)
postgres-# SELECT users.userid, users.points
postgres-# FROM users
postgres-# LEFT JOIN (
postgres(#      SELECT userid, MAX(timestamp_dump) AS timestamp_dump
postgres(#      FROM balances
postgres(#      GROUP BY userid
postgres(#      ) AS b1 USING(userid)
postgres-# LEFT JOIN balances b2 USING(userid,timestamp_dump)
postgres-# WHERE users.points != b2.points
postgres-#      OR b2.points IS NULL ;
INSERT 0 10001
postgres=# UPDATE users
postgres-# SET points = random()*100
postgres-# WHERE random()< .3;
UPDATE 2976
postgres=# select now();
            now
----------------------------
 2008-07-19 06:26:31.359-07
(1 row)

postgres=# INSERT INTO balances (userid, points)
postgres-# SELECT users.userid, users.points
postgres-# FROM users
postgres-# LEFT JOIN (
postgres(#      SELECT userid, MAX(timestamp_dump) AS timestamp_dump
postgres(#      FROM balances
postgres(#      GROUP BY userid
postgres(#      ) AS b1 USING(userid)
postgres-# LEFT JOIN balances b2 USING(userid,timestamp_dump)
postgres-# WHERE users.points != b2.points
postgres-#      OR b2.points IS NULL ;
INSERT 0 2946
postgres=# select now();
            now
----------------------------
 2008-07-19 06:26:31.593-07
(1 row)





mysql> DROP TABLE IF EXISTS users, balances, integers;
Query OK, 0 rows affected (0.41 sec)

mysql> CREATE TABLE users(
    -> userid INT PRIMARY KEY AUTO_INCREMENT,
    -> points INT);
Query OK, 0 rows affected (0.13 sec)

mysql> CREATE TABLE balances(
    -> userid INT,
    -> points INT,
    -> timestamp_dump TIMESTAMP,
    -> PRIMARY KEY(userid,timestamp_dump) );
Query OK, 0 rows affected (0.13 sec)

mysql> CREATE TABLE integers(i tinyint);
Query OK, 0 rows affected (0.11 sec)

mysql> INSERT INTO integers(i)
    -> VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
Query OK, 10 rows affected (0.06 sec)
Records: 10  Duplicates: 0  Warnings: 0

mysql> INSERT INTO users(points)
    -> SELECT rand()*100
    -> FROM integers AS i1,
    -> integers AS i2,
    -> integers AS i3,
    -> integers AS i4
    -> WHERE i1.i + i2.i *10 + i3.i * 100 + i4.i *1000 < 10000 ;
Query OK, 10000 rows affected (0.31 sec)
Records: 10000  Duplicates: 0  Warnings: 0

mysql> INSERT INTO balances (userid, points)
    -> SELECT users.userid, users.points
    -> FROM users
    -> LEFT JOIN (
    ->  SELECT userid, MAX(timestamp_dump) AS 'timestamp_dump'
    ->  FROM balances
    ->  GROUP BY userid
    ->  ) AS b1 USING(userid)
    -> LEFT JOIN balances b2 USING(userid,timestamp_dump)
    -> WHERE users.points != b2.points
    ->  OR b2.points IS NULL ;
Query OK, 10000 rows affected (0.38 sec)
Records: 10000  Duplicates: 0  Warnings: 0

mysql> UPDATE users
    -> SET points = rand()*100
    -> WHERE rand()< .3;
Query OK, 2970 rows affected (0.16 sec)
Rows matched: 2990  Changed: 2970  Warnings: 0

mysql> INSERT INTO balances (userid, points)
    -> SELECT users.userid, users.points
    -> FROM users
    -> LEFT JOIN (
    ->  SELECT userid, MAX(timestamp_dump) AS 'timestamp_dump'
    ->  FROM balances
    ->  GROUP BY userid
    ->  ) AS b1 USING(userid)
    -> LEFT JOIN balances b2 USING(userid,timestamp_dump)
    -> WHERE users.points != b2.points
    ->  OR b2.points IS NULL ;
Query OK, 2970 rows affected (20.05 sec)
Records: 2970  Duplicates: 0  Warnings: 0



-- 
Rob Wultsch

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

Reply via email to