473,395 Members | 1,637 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

MySQL is making me nuts!

Hello all, this might better be suited for the MySQL newsgroup, but I
figured I'ld post here and see if anyone can help me.

I'm trying to create a simple transaction handling system where users
pay eachother via points of a sort.
I have a table where each transaction is stored, in a single row.
It looks like this

transid,from_user,from_amount,to_user,to_amount

Given the above, I just want a simple single SQL statement that can
return a full balance.
Now originally I did this in PHP by querying the DB with the following.

$query[0] = "SELECT SUM(to_amount) WHERE to_user = '$user->uid'";
$query[1] = "SELECT SUM(from_amount) WHERE from_user = '$user->uid'";
$deposits = mysql_result(mysql_query($query[0]);
$withdrawls = mysql_result(mysql_query($query[1]);
$balance = $deopsits - $withdrawls;

This works great, so I populated the DB with over 100,000 records and
now page loads take 75-80 seconds for the total balance sheet page (I
just loop through each user, and there are 100 users), and upwards of
10 seconds on a single user query.

After analyzing the code in the profiler (I'm using Zend), I found the
largest optimization I could make would be to cut out the 2 queries
variable assignment and simple math (basically all of the code above),
and move it into a single SQL statement that does all the math.

This SHOULD be elementary, but unfortunately, MySQL doesn't like my
solution, and searching everywhere I could, I can't seem to find where
anything similar has every been tried. But come on, I know I can't be
the first person in history with a similar need for a query like this.

Here is the most elegant solution I could come up with, in all it's raw
SQL glory.

SELECT SUM(to_amount - from_amount) as balance FROM
((SELECT from_amount as withdrawls FROM transactions WHERE from_user =
'1')
(SELECT to_amount as deposits FROM transactions WHERE to_user = '1'));

Sadly, even though by every measure I can find it SHOULD work, it just
doesn't.
I keep getting

#1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near '(SELECT to_amount as deposits FROM transactions WHERE to_user =
'1'))' at line 3

I'm just not seeing it, as far as I can tell this should work.
Any Ideas?

Oct 26 '05 #1
10 2106
Just a note I'ld thought I'ld mention.
The other logical solution is this.

SELECT deposits - withdrawls as balance FROM(
(SELECT sum(from_amount ) as withdrawls FROM transactions WHERE
from_user = '1' UNION
SELECT sum(to_amount) as deposits FROM transactions WHERE to_user =
'1' )

Which produces the following error

#1248 - Every derived table must have its own alias

I'm going into a corner to cry now.

sm*****@gmail.com wrote:
Hello all, this might better be suited for the MySQL newsgroup, but I
figured I'ld post here and see if anyone can help me.

I'm trying to create a simple transaction handling system where users
pay eachother via points of a sort.
I have a table where each transaction is stored, in a single row.
It looks like this

transid,from_user,from_amount,to_user,to_amount

Given the above, I just want a simple single SQL statement that can
return a full balance.
Now originally I did this in PHP by querying the DB with the following.

$query[0] = "SELECT SUM(to_amount) WHERE to_user = '$user->uid'";
$query[1] = "SELECT SUM(from_amount) WHERE from_user = '$user->uid'";
$deposits = mysql_result(mysql_query($query[0]);
$withdrawls = mysql_result(mysql_query($query[1]);
$balance = $deopsits - $withdrawls;

This works great, so I populated the DB with over 100,000 records and
now page loads take 75-80 seconds for the total balance sheet page (I
just loop through each user, and there are 100 users), and upwards of
10 seconds on a single user query.

After analyzing the code in the profiler (I'm using Zend), I found the
largest optimization I could make would be to cut out the 2 queries
variable assignment and simple math (basically all of the code above),
and move it into a single SQL statement that does all the math.

This SHOULD be elementary, but unfortunately, MySQL doesn't like my
solution, and searching everywhere I could, I can't seem to find where
anything similar has every been tried. But come on, I know I can't be
the first person in history with a similar need for a query like this.

Here is the most elegant solution I could come up with, in all it's raw
SQL glory.

SELECT SUM(to_amount - from_amount) as balance FROM
((SELECT from_amount as withdrawls FROM transactions WHERE from_user =
'1')
(SELECT to_amount as deposits FROM transactions WHERE to_user = '1'));

Sadly, even though by every measure I can find it SHOULD work, it just
doesn't.
I keep getting

#1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near '(SELECT to_amount as deposits FROM transactions WHERE to_user =
'1'))' at line 3

I'm just not seeing it, as far as I can tell this should work.
Any Ideas?


Oct 26 '05 #2
This works great, so I populated the DB with over 100,000 records and
now page loads take 75-80 seconds for the total balance sheet page (I
just loop through each user, and there are 100 users), and upwards of
10 seconds on a single user query.


Forget the SQL, the syntax is all over the place. Go back to the
original queries, but create indexes on columns `from_user` and
`to_user`.

---
Steve

Oct 26 '05 #3
sm*****@gmail.com wrote:
Hello all, this might better be suited for the MySQL newsgroup, but I
figured I'ld post here and see if anyone can help me.

I'm trying to create a simple transaction handling system where users
pay eachother via points of a sort.
I have a table where each transaction is stored, in a single row.
It looks like this

transid,from_user,from_amount,to_user,to_amount

Given the above, I just want a simple single SQL statement that can
return a full balance.
Now originally I did this in PHP by querying the DB with the following.

$query[0] = "SELECT SUM(to_amount) WHERE to_user = '$user->uid'";
$query[1] = "SELECT SUM(from_amount) WHERE from_user = '$user->uid'";
$deposits = mysql_result(mysql_query($query[0]);
$withdrawls = mysql_result(mysql_query($query[1]);
$balance = $deopsits - $withdrawls;

This works great, so I populated the DB with over 100,000 records and
now page loads take 75-80 seconds for the total balance sheet page (I
just loop through each user, and there are 100 users), and upwards of
10 seconds on a single user query.

After analyzing the code in the profiler (I'm using Zend), I found the
largest optimization I could make would be to cut out the 2 queries
variable assignment and simple math (basically all of the code above),
and move it into a single SQL statement that does all the math.

This SHOULD be elementary, but unfortunately, MySQL doesn't like my
solution, and searching everywhere I could, I can't seem to find where
anything similar has every been tried. But come on, I know I can't be
the first person in history with a similar need for a query like this.

Here is the most elegant solution I could come up with, in all it's raw
SQL glory.

SELECT SUM(to_amount - from_amount) as balance FROM
((SELECT from_amount as withdrawls FROM transactions WHERE from_user =
'1')
(SELECT to_amount as deposits FROM transactions WHERE to_user = '1'));

Sadly, even though by every measure I can find it SHOULD work, it just
doesn't.
I keep getting

#1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near '(SELECT to_amount as deposits FROM transactions WHERE to_user =
'1'))' at line 3

I'm just not seeing it, as far as I can tell this should work.
Any Ideas?


check your mysql version, sub-queries (select inside select) are still
relatively new (v4.1+)...

SELECT
(deposits - withdrawls) as balance
FROM
(
SELECT
(
SELECT sum(amount) as amount
FROM transactions
WHERE to_user = '1'
GROUP BY to_user
) as deposits,
(
SELECT sum(amount) as amount
FROM transactions
WHERE from_user = '1'
GROUP BY from_user
) as withdrawls
) as result_table

You may need to edit a little as I didn't use the from_amount since I
was assuming that the amount of the transaction would be equal for the
to and from sides... transactions table would have the following fields:

id, from_user, to_user, amount

HTH

--
Justin Koivisto, ZCE - ju****@koivi.com
http://koivi.com
Oct 26 '05 #4
sm*****@gmail.com wrote:
Just a note I'ld thought I'ld mention.
The other logical solution is this.

SELECT deposits - withdrawls as balance FROM(
(SELECT sum(from_amount ) as withdrawls FROM transactions WHERE
from_user = '1' UNION
SELECT sum(to_amount) as deposits FROM transactions WHERE to_user =
'1' )

Which produces the following error

#1248 - Every derived table must have its own alias

I'm going into a corner to cry now.


at the very end of that statement, simply add " as table1" and you
should be good.

--
Justin Koivisto, ZCE - ju****@koivi.com
http://koivi.com
Oct 26 '05 #5
Woohoo! That almost worked, but this actually does!

SELECT (
deposits - withdrawls
) AS balance
FROM (

SELECT (

SELECT sum( to_amount ) AS amount
FROM transactions
WHERE to_user = '1'
GROUP BY to_user

) AS deposits, (

SELECT sum( from_amount ) AS amount
FROM transactions
WHERE from_user = '1'
GROUP BY from_user
) AS withdrawls
) AS result_table

Thank you VERY much, the difference is that the from_amount and
to_amount can and will tend to be very different, due to a fee which is
extracted in some cases, in some types of transactions. But no bother,
once I seen how to do it, it made all the difference.
Thank you!

Justin Koivisto wrote:
sm*****@gmail.com wrote:
Hello all, this might better be suited for the MySQL newsgroup, but I
figured I'ld post here and see if anyone can help me.

I'm trying to create a simple transaction handling system where users
pay eachother via points of a sort.
I have a table where each transaction is stored, in a single row.
It looks like this

transid,from_user,from_amount,to_user,to_amount

Given the above, I just want a simple single SQL statement that can
return a full balance.
Now originally I did this in PHP by querying the DB with the following.

$query[0] = "SELECT SUM(to_amount) WHERE to_user = '$user->uid'";
$query[1] = "SELECT SUM(from_amount) WHERE from_user = '$user->uid'";
$deposits = mysql_result(mysql_query($query[0]);
$withdrawls = mysql_result(mysql_query($query[1]);
$balance = $deopsits - $withdrawls;

This works great, so I populated the DB with over 100,000 records and
now page loads take 75-80 seconds for the total balance sheet page (I
just loop through each user, and there are 100 users), and upwards of
10 seconds on a single user query.

After analyzing the code in the profiler (I'm using Zend), I found the
largest optimization I could make would be to cut out the 2 queries
variable assignment and simple math (basically all of the code above),
and move it into a single SQL statement that does all the math.

This SHOULD be elementary, but unfortunately, MySQL doesn't like my
solution, and searching everywhere I could, I can't seem to find where
anything similar has every been tried. But come on, I know I can't be
the first person in history with a similar need for a query like this.

Here is the most elegant solution I could come up with, in all it's raw
SQL glory.

SELECT SUM(to_amount - from_amount) as balance FROM
((SELECT from_amount as withdrawls FROM transactions WHERE from_user =
'1')
(SELECT to_amount as deposits FROM transactions WHERE to_user = '1'));

Sadly, even though by every measure I can find it SHOULD work, it just
doesn't.
I keep getting

#1064 - You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near '(SELECT to_amount as deposits FROM transactions WHERE to_user =
'1'))' at line 3

I'm just not seeing it, as far as I can tell this should work.
Any Ideas?


check your mysql version, sub-queries (select inside select) are still
relatively new (v4.1+)...

SELECT
(deposits - withdrawls) as balance
FROM
(
SELECT
(
SELECT sum(amount) as amount
FROM transactions
WHERE to_user = '1'
GROUP BY to_user
) as deposits,
(
SELECT sum(amount) as amount
FROM transactions
WHERE from_user = '1'
GROUP BY from_user
) as withdrawls
) as result_table

You may need to edit a little as I didn't use the from_amount since I
was assuming that the amount of the transaction would be equal for the
to and from sides... transactions table would have the following fields:

id, from_user, to_user, amount

HTH

--
Justin Koivisto, ZCE - ju****@koivi.com
http://koivi.com


Oct 26 '05 #6
Ok, thanks that helps quite a bit, the single user page load was cut by
25% by using phpmyadmin to create indexes on from_user and to_user,
which I assume is what you meant, since I have no clue how to create an
index any other way.

But the page load times are still spectacularly high.
It seems to me, that this should still be something handled via a
simple DB query.
I mean really it SHOULD be as simple as SELECT SUM(to_amount) WHERE
to_user = 1 - SUM(from_amount) WHERE from_user = 1

However that doesn't appear to work either :(

Steve wrote:
This works great, so I populated the DB with over 100,000 records and
now page loads take 75-80 seconds for the total balance sheet page (I
just loop through each user, and there are 100 users), and upwards of
10 seconds on a single user query.


Forget the SQL, the syntax is all over the place. Go back to the
original queries, but create indexes on columns `from_user` and
`to_user`.

---
Steve


Oct 26 '05 #7
Ok, I don't know how but this got places in the wrong order in the News
Group.
Anyways problem is solved.

sm*****@gmail.com wrote:
Ok, thanks that helps quite a bit, the single user page load was cut by
25% by using phpmyadmin to create indexes on from_user and to_user,
which I assume is what you meant, since I have no clue how to create an
index any other way.

But the page load times are still spectacularly high.
It seems to me, that this should still be something handled via a
simple DB query.
I mean really it SHOULD be as simple as SELECT SUM(to_amount) WHERE
to_user = 1 - SUM(from_amount) WHERE from_user = 1

However that doesn't appear to work either :(

Steve wrote:
This works great, so I populated the DB with over 100,000 records and
now page loads take 75-80 seconds for the total balance sheet page (I
just loop through each user, and there are 100 users), and upwards of
10 seconds on a single user query.


Forget the SQL, the syntax is all over the place. Go back to the
original queries, but create indexes on columns `from_user` and
`to_user`.

---
Steve


Oct 26 '05 #8
NC
sm*****@gmail.com wrote:

I'm trying to create a simple transaction handling system where users
pay eachother via points of a sort.
I have a table where each transaction is stored, in a single row.
It looks like this

transid,from_user,from_amount,to_user,to_amount
Why do you have from_amount and to_amount? Aren't they supposed
to be equal? Or is there a "house take" of some kind?
Given the above, I just want a simple single SQL statement that can
return a full balance.


Bad idea. If you want a transaction system, create a transaction
system. You need to add a `balance` column to the table where
user data is stored. Both the `users` table and `transactions`
table must be InnoDB. Then you can actually do transaction
processing:

BEGIN;
INSERT INTO `transactions`
SET from_user = [from_user],
from_amount = [from_amount],
to_user = [to_user],
to_amount = [to_amount];
UPDATE `users`
SET `balance` = `balance` - [from_amount]
WHERE `id` = [from_user];
UPDATE `users`
SET `balance` = `balance` + [to_amount]
WHERE `id` = [to_user];
COMMIT;

This way, balance is readily available as a single number;
there's no need to query records from the beginning of the
universe to look up balances...

Cheers,
NC

Oct 26 '05 #9
Yes there is a house take, but there is also a percieved value here as
well.
The easiest way to understand what I am doing would be to consider it
like a currency conversion system or a market making system (in reality
this is for a role playing game with multiple regional currencies but I
think you catch my drift here.

In this instance we have USER 1 who is converting Gold to Clamshells
because USER 2 would like to be paid in ClamShells.
The transaction would look something like this.

assuming status is one of 3 values, proposed, accepted or rejected.

INSERT INTO transactions from_user, from_amount, from_cur, to_user,
to_amount,to_cur, fee, status

And actually is more like

INSERT INTO tranactions '1', '100','gold','2','900','clamshells','100',
'proposed'

Since a user can have "accounts" in anything tradeable in game which
amounts to over 200 regional currencies, I made a decision to not have
a "balance" table which seemed to be very exploitable.

On the other hand I never considered, updating the balance table on
each transaction for each currency type involved, and will have to look
closer at it.

In the final analysis, the only purpose for doing this on the website,
is to give weary travelers a place buy and sell thier wares w/o using
an auction channel or a forum that could get crowded like in EQ.

Anyways, thanks for the advice, I'll look into it and see how it works
out.

NC wrote:
sm*****@gmail.com wrote:

I'm trying to create a simple transaction handling system where users
pay eachother via points of a sort.
I have a table where each transaction is stored, in a single row.
It looks like this

transid,from_user,from_amount,to_user,to_amount


Why do you have from_amount and to_amount? Aren't they supposed
to be equal? Or is there a "house take" of some kind?
Given the above, I just want a simple single SQL statement that can
return a full balance.


Bad idea. If you want a transaction system, create a transaction
system. You need to add a `balance` column to the table where
user data is stored. Both the `users` table and `transactions`
table must be InnoDB. Then you can actually do transaction
processing:

BEGIN;
INSERT INTO `transactions`
SET from_user = [from_user],
from_amount = [from_amount],
to_user = [to_user],
to_amount = [to_amount];
UPDATE `users`
SET `balance` = `balance` - [from_amount]
WHERE `id` = [from_user];
UPDATE `users`
SET `balance` = `balance` + [to_amount]
WHERE `id` = [to_user];
COMMIT;

This way, balance is readily available as a single number;
there's no need to query records from the beginning of the
universe to look up balances...

Cheers,
NC


Oct 26 '05 #10
On 26 Oct 2005 11:40:09 -0700, sm*****@gmail.com top posted like a
newbie and wrote:
Ok, I don't know how but this got places in the wrong order in the News
Group.
Anyways problem is solved.
You might also try the new comp.databases.mysql newsgroup for further
mysql questions.
sm*****@gmail.com wrote:
Ok, thanks that helps quite a bit, the single user page load was cut by
25% by using phpmyadmin to create indexes on from_user and to_user,
which I assume is what you meant, since I have no clue how to create an
index any other way.

But the page load times are still spectacularly high.
It seems to me, that this should still be something handled via a
simple DB query.
I mean really it SHOULD be as simple as SELECT SUM(to_amount) WHERE
to_user = 1 - SUM(from_amount) WHERE from_user = 1

However that doesn't appear to work either :(

Steve wrote:
> > This works great, so I populated the DB with over 100,000 records and
> > now page loads take 75-80 seconds for the total balance sheet page (I
> > just loop through each user, and there are 100 users), and upwards of
> > 10 seconds on a single user query.
>
> Forget the SQL, the syntax is all over the place. Go back to the
> original queries, but create indexes on columns `from_user` and
> `to_user`.
>
> ---
> Steve

--
gburnore at DataBasix dot Com
---------------------------------------------------------------------------
How you look depends on where you go.
---------------------------------------------------------------------------
Gary L. Burnore | ÝÛ³ºÝ³Þ³ºÝ³³Ýۺݳ޳ºÝ³Ý³Þ³ºÝ³ÝÝÛ³
| ÝÛ³ºÝ³Þ³ºÝ³³Ýۺݳ޳ºÝ³Ý³Þ³ºÝ³ÝÝÛ³
Official .sig, Accept no substitutes. | ÝÛ³ºÝ³Þ³ºÝ³³Ýۺݳ޳ºÝ³Ý³Þ³ºÝ³ÝÝÛ³
| ÝÛ 0 1 7 2 3 / Ý³Þ 3 7 4 9 3 0 Û³
Black Helicopter Repair Services, Ltd.| Official Proof of Purchase
================================================== =========================
Oct 26 '05 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: David | last post by:
Hi, I am running Debian 3.0r1 with Apache 1.3.27, MySQL 3.23.49 and PHP 4.3.3RC3. I installed Apache and MySQL when I originally installed Debian and these work fine. I recently wanted to run...
1
by: Wayne... | last post by:
I'm trying to get asp to conect to a MySQL database, I've tried copying a few examples online that I found and I always get a 500 error with the code below. what am i doing wrong? any examples of...
6
by: Dave | last post by:
Ok I have an interesting problem. I have written a database in Access to connect to our web shop and update prices etc from a supplier feed. It works almost perfectly! The prices are doubles, I...
175
by: Sai Hertz And Control Systems | last post by:
Dear all, Their was a huge rore about MySQL recently for something in java functions now theirs one more http://www.mysql.com/doc/en/News-5.0.x.html Does this concern anyone. What I...
11
by: Mark Cubitt | last post by:
the reason I ask is I have always used postgres at home and work, but my new web host only has mysql :( I want to know what sort of differences I will have in regards to programming php/perl...
39
by: windandwaves | last post by:
Hi Folk I have to store up to eight boolean bits of information about an item in my database. e.g. with restaurant drive-through facility yellow windows
1
by: lynnem | last post by:
Hi there, I'm new to php & mysql and would really appreciate some help with the following: I'd like to display a list of products and a string showing the categories they fall into: - a product...
13
by: Ciaran | last post by:
Hi All, Is it faster to have mySql look up as much data as possible in one complex query or to have php do all the complex processing and submit lots of simple queries to the mysql database? ...
20
by: _mario.lat | last post by:
hallo, I use PHP and I'd like to not write in hardcoded way password and login to access to mysql. how to not write password in code for access to mysql? How can I do? I'd like that who see my...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.