i have a user database and i have to assign a user id for them for example AA01
AND after insert 1 person into database i have to insert another person with user id AA02 AND i have increment it and so on.
what i have already tried is
$sql_user_id=mysql_query("SELECT MAX(user_id) FROM `users` desc LIMIT 1");
$new_array = explode('AA',$sql_user_id);
$number=$new_array[1];
$newnumber=$number+1;
and i am getting wrong with result Resource id #5
You have to fetch the query results before you can use them.
$result=mysql_query("SELECT MAX(user_id) AS maxId FROM `users` desc LIMIT 1");
$sql_user_id = mysql_fetch_assoc($result);
$new_array = explode('AA',$sql_user_id['maxId']);
$number=$new_array[1];
$newnumber=$number+1;
FYI, I added an alias to your query as it makes referencing a value returned from a function much easier to do.
mysql_query() returns a resource, not a value you can operate directly. You have to fetch the value from this resource first:
$res = mysql_query('SELECT MAX(`user_id`) FROM `users`');
$val = mysql_fetch_row($res);
$new_array = explode('AA', $val[0]);
...
Also, notice that MAX() causes an implicit grouping to happen. So there is no order, and there is only one result. Specifying any of this in your query is futile.
In addition, notice that, since user_id is aparently a text, it might not work as expected. When sorting text, 2 comes after 10. You may need to use a different reference to fetch the latest user_id. If you can help it, don't use text to index your records.
Related
Getting the Value:
I've got the levenshtein_ratio function, from here, queued up in my MySQL database. I run it in the following way:
$stmt = $db->prepare("SELECT r_id, val FROM table WHERE levenshtein_ratio(:input, someval) > 70");
$stmt->execute(array('input' => $input));
$result = $stmt->fetchAll();
if(count($result)) {
foreach($result as $row) {
$out .= $row['r_id'] . ', ' . $row['val'];
}
}
And it works a treat, exactly as expected. But I was wondering, is there a nice way to also get the value that levenshtein_ratio() calculates?
I've tried:
$stmt = $db->prepare("SELECT levenshtein_ratio(:input, someval), r_id, val FROM table WHERE levenshtein_ratio(:input, someval) > 70");
$stmt->execute(array('input' => $input));
$result = $stmt->fetchAll();
if(count($result)) {
foreach($result as $row) {
$out .= $row['r_id'] . ', ' . $row['val'] . ', ' . $row[0];
}
}
and it does technically work (I get the percentage from the $row[0]), but the query is a bit ugly, and I can't use a proper key to get the value, like I can for the other two items.
Is there a way to somehow get a nice reference for it?
I tried:
$stmt = $db->prepare("SELECT r_id, val SET output=levenshtein_ratio(:input, someval) FROM table WHERE levenshtein_ratio(:input, someval) > 70");
modelling it after something I found online, but it didn't work, and ends up ruining the whole query.
Speeding It Up:
I'm running this query for an array of values:
foreach($parent as $input){
$stmt = ...
$stmt->execute...
$result = $stmt->fetchAll();
... etc
}
But it ends up being remarkably slow. Like 20s slow, for an array of only 14 inputs and a DB with about 350 rows, which is expected to be in the 10,000's soon. I know that putting queries inside loops is naughty business, but I'm not sure how else to get around it.
EDIT 1
When I use
$stmt = $db->prepare("SELECT r_id, val SET output=levenshtein_ratio(:input, someval) FROM table WHERE levenshtein_ratio(:input, someval) > 70");
surely that's costing twice the time as if I only calculated it once? Similar to having $i < sizeof($arr); in a for loop?
To clean up the column names you can use "as" to rename the column of the function. At the same time you can speed things up by using that column name in your where clause so the function is only executed once.
$stmt = $db->prepare("SELECT r_id, levenshtein_ratio(:input, someval) AS val FROM table HAVING val > 70");
If it is still too slow you might consider a c library like https://github.com/juanmirocks/Levenshtein-MySQL-UDF
doh - forgot to switch "where" to "having", as spencer7593 noted.
I'm assuming that `someval` is an unqalified reference to a column in the table. While you may understand that without looking at the table definition, someone else reading the SQL statement can't tell. As an aid to future readers, consider qualifying your column references with the name of the table or (preferably) a short alias assigned to the table in the statement.
SELECT t.r_id
, t.val
FROM `table` t
WHERE levenshtein_ratio(:input, t.someval) > 70
That function in the WHERE clause has to be evaluated for every row in the table. There's no way to get MySQL to build an index on that. So there's no way to get MySQL to perform an index range scan operation.
It might be possible to get MySQL to use an index for the query, for example, if the query had an ORDER BY t.val clause, or if there is a "covering index" available.
But that doesn't get around the issue of needing to evaluate the function for every row. (If the query had other predicates that excluded rows, then the function wouldn't necessarily need be evaluated for the excluded rows.)
Adding the expression to the SELECT list really shouldn't be too expensive if the function is declared to be DETERMINISTIC. A second call to a DETERMINISTIC function with the same arguments can reuse the value returned for the previous execution. (Declaring a function DETERMINISTIC essentially means that the function is guaranteed to return the same result when given the same argument values. Repeated calls will return the same value. That is, the return value depends only the argument values, and doesn't depend on anything else.
SELECT t.r_id
, t.val
, levenshtein_ratio(:input, t.someval) AS lev_ratio
FROM `table` t
WHERE levenshtein_ratio(:input2, t.someval) > 70
(Note: I used a distinct bind placeholder name for the second reference because PDO doesn't handle "duplicate" bind placeholder names as we'd expect. (It's possible that this has been corrected in more recent versions of PDO. The first "fix" for the issue was an update to the documentation noting that bind placeholder names should appear only once in statement, if you needed two references to the same value, use two different placeholder names and bind the same value to both.)
If you don't want to repeat the expression, you could move the condition from the WHERE clause to the HAVING, and refer to the expression in the SELECT list by the alias assigned to the column.
SELECT t.r_id
, t.val
, levenshtein_ratio(:input, t.someval) AS lev_ratio
FROM `table` t
HAVING lev_ratio > 70
The big difference between WHERE and HAVING is that the predicates in the WHERE clause are evaluated when the rows are accessed. The HAVING clause is evaluated much later, after the rows have been accessed. (That's a brief explanation of why the HAVING clause can reference columns in the SELECT list by their alias, but the WHERE clause can't do that.)
If that's a large table, and a large number of rows are being excluded, there might be a significant performance difference using the HAVING clause.. there may be a much larger intermediate set created.
To get an "index used" for the query, a covering index is the only option I see.
ON `table` (r_id, val, someval)
With that, MySQL can satisfy the query from the index, without needing to lookup pages in the underlying table. All of the column values the query needs are available from the index.
FOLLOWUP
To get an index created, we would need to create a column, e.g.
lev_ratio_foo FLOAT
and pre-populate with the result from the function
UPDATE `table` t
SET t.lev_ratio_foo = levenshtein_ratio('foo', t.someval)
;
Then we could create an index, e.g.
... ON `table` (lev_ratio_foo, val, r_id)
And re-write the query
SELECT t.r_id
, t.val
, t.lev_ratio_foo
FROM `table` t
WHERE t.lev_ratio_foo > 70
With that query, MySQL can make use of an index range scan operation on an index with lev_ratio_foo as the leading column.
Likely, we would want to add BEFORE INSERT and BEFORE UPDATE triggers to maintain the value, when a new row is added to the table, or the value of the someval column is modified.
That pattern could be extended, additional columns could be added for values other than 'foo'. e.g. 'bar'
UPDATE `table` t
SET t.lev_ratio_bar = levenshtein_ratio('bar', t.someval)
Obviously that approach isn't going to be scalable for a broad range of input values.
Hi there i am working on PHP code that is selecting columns from two tables.
Here is my code:
$result2 = mysql_query("SELECT *
FROM `videos`, `m_subedvids`
WHERE `videos.approved`='yes' AND
`videos.user_id`='$subedFOR'
ORDER BY `videos.indexer`
DESC LIMIT $newVID");
while($row2 = mysql_fetch_array($result2))
{
$indexer = addslashes($row2['videos.indexer']);
$title_seo = addslashes($row2['videos.title_seo']);
$video_id = addslashes($row2['videos.video_id']);
$title = addslashes($row2['videos.title']);
$number_of_views = addslashes($row2['videos.number_of_views']);
$video_length = addslashes($row2['videos.video_length']);
}
When i try to print $indexer with echo $indexer; it's not giving me any results.
Where is my mistake in this code?
It seems to me like the key 'indexer' isn't in your results. It's hard to tell, since you haven't listed a definition for your table and you're using SELECT * so we can't see the names.
It makes the program easier to read later, if instead of SELECT *..., you use SELECT col1, col2, .... Yes, SELECT * will save you some typing right now, but you'll lose that time later when you or anyone else who works on your code has to check the table definition every time they work with that line of code.
So, try changing your query to explicitly select the columns you use. If it's an invalid column you'll get an error right away rather than this silent failure you're getting now, and you'll thank yourself later as well.
So long as videos.indexer is a unique field name among all tables used in the query you can change
$indexer = addslashes($row2['videos.indexer']);
to
$indexer = addslashes($row2['indexer']);
You don't need to (or can not) use the table name when referring to the result.
I tried this way:
$result = odbc_exec($connection, 'SELECT id FROM MyTable WHERE id = ##Identity');
but it gives me
syntax error: unexpected T_VARIABLE
edit: here's complete logic thanks to your help:
$result = odbc_exec($connection, 'INSERT data into the table;SELECT SCOPE_IDENTITY() AS id;');
$row = odbc_fetch_array($result); //this line gives the error!
$id = $row['id'];
edit2: I missed a ";" =_=
Anyway scope_identity does not work: gives
no tuples available at this index
on fetcharray call
After inserting a row, you can look up the last inserted id using scope_identity(). There's no need to look it up in the original table:
SELECT SCOPE_IDENTIY()
If the row was inserted on another connection, you can query the maximum value of id:
SELECT max(id) FROM MyTable
Why aren't you just saying:
$result = obdc_exec('INSERT dbo.MyTable(...) VALUES(...); SELECT id = SCOPE_IDENTITY();');
Or better yet, put the logic into a stored procedure and stop burying ad hoc SQL in your application code.
EDIT because PHP is weird and may treat your INSERT as a resultset, you may need to play with this (pardon me, but I am not a PHP expert):
odbc_next_result($result);
You may also be able to suppress the first result by saying:
SET NOCOUNT ON; INSERT ...; SELECT id = SCOPE_IDENTITY();
Again, I don't know, I don't do PHP. I still think you should be doing this in a stored procedure.
I'm trying to create an array, and then sort the objects by time, from a mysql_query.
This is what happens:
When a player has completed his turn, I update the database. I set the database variable "lastTurn" to the current time.
$nickname = $_POST['name'];
$lastTurn = date();
$myTurn = NO;
$query ... update query
Now I need to find out who the next player is, and send the turn to him/her.
$query = "SELECT * FROM active_users_table WHERE match_id='12345'
This gives me all the player associated with the current game.
But now I don't know how to continue.
I want to put all the players into an array, and then sort it after turnDate i guess, to see who the next player is. Like a poker game. I also need to check another variable in the database, "havePlayerLost", to see if he still is active in the game. If he have lost, then get the next player who is active, and with the highest turnDate.
Any advice is very appreciated.
Thanks
I would suggest you let MySQL/SQL do a little more work than you're doing right now. The SQL query you use to update the player, can also contain the current date / time in the right format.
player_lastTurn = NOW()
When it comes to sorting your array, I'd suggest you let MySQL handle this one aswell:
ORDER BY player_lastTurn ASC
ASCending means it will give you the oldest DateTime for that cellname within the entire database.
When you use the results of these queries and build your array using it, you're array will automatically be in the correct order.
The same applies for the "lost players", so you automatically not include them in the array when you're not loading it.
To get the player sorted try to change the query adding ' ORDER BY turnDate ASC '
$query = "SELECT * FROM active_users_table WHERE match_id='12345' ORDER BY turnDate ASC"
For the variable "havePlayerLost" I think you can change the query too like this adding ' havePlayerLost = false '
$query = "SELECT * FROM active_users_table WHERE match_id='12345' AND havePlayerLost = false ORDER BY turnDate ASC"
try this query
$query = "SELECT * FROM active_users_table WHERE match_id='12345'
and status !='havePlayerLost'
order by lastTurn Asc
I want to count all the rows and at the same time list them as I usually do, using mysql_fetch_object. I thought I'd do something like this;
$total = mysql_query("SELECT *, COUNT(*) AS totalfound FROM img WHERE state='0'");
But I can't seem to wrap my head around how to get the values out - I just get the first item in the table when I run this;
while ($record = mysql_fetch_object($total)) { echo $record->id; }
If I want to get the totalfound I could do this;
$result = mysql_fetch_assoc($total);
$count = $result['totalfound'];
...but then I can't get the rest. I know I'm thinking wrong but can't seem to get it to work. Can you guys please help me out? Thanks!
Once thing I forgot to mention: mysql_num_rows is too slow, I was thinking of using count(*) instead. As an example, mysql_num_rows on the entire table takes everything from 3 to 9 seconds, and a count(*) always takes 0.6 seconds, getting the same results.
A count is an aggregate function, you cannot select both rows and aggregates without using group by. MySQL will let you do it without the group by, and will produce unpredictable results.
Just use the query without count to get the rows, and use mysql_num_rows() on the result.
Edit: If mysql_num_rows() is slow, you must be returning a lot of rows. You'd then better execute two queries, one simply select count(*) as numrows ..., and one to retreive your data.
Try to add proper indexes and the count(*) will execute within a few miliseconds.
You really don't want this in one query. Every row will then have a column that states how many rows there are, which is unrelated to that row.
Why not just list them normally and get the count by the inbuilt function?
$result = mysql_query("SELECT * FROM img WHERE state='0'");
$count = mysql_num_rows($result);
while ($row = mysql_fetch_array($result))
{
//do your thing here
}
Editing in response to your edit
In normal circumstances, where you only want the Count, a Count() would be far faster than mysql_num_rows() because Count() would only return the count. In your case, since you want the records anyway, mysql_num_rows() should be faster.
If I understand what you need, I think you could use:
$result = mysql_query("SELECT * FROM img WHERE state='0'");
$num_rows = mysql_num_rows($result);
With $result you can get all rows the way you're used to, while $num_rows has the number of returned rows from database.
Aside from the Marco's right answer,
why can't you make it the same way, echo $record->totalfound;?
As for the "mysql_num_rows being slow" - it is no more a delusion.
You have just heard something but didn't get the point.
mysql_num_rows itself isn't being slow by any means.
it is gathering data rows being slow, not getting them count.
mysql_num_rows indeed is slower than count(*) if you need only that number, not all the data
but if you are getting your data anyway, mysql_num_rows is exactly what you need
Use KISS theory and do the below
while ($record = mysql_fetch_object($total)) {$totalData[] = $record; }
count($totalData) // returns total number of rows
Count
My dear haven't you listen about mysql_num_rows
$total = mysql_query("SELECT * FROM img WHERE state='0'");
$total_found=mysql_num_rows($total);