mySQL SUM and Ordering - php

We have a table which inserts a row each day and updates it with data.
I have the following query to get the total amount of clicks from the table:
SELECT SUM(`total_clicks`) AS clicks, `last_updated` FROM `reporting` WHERE `unique_id` = 'xH7' ORDER BY `last_updated` DESC
When pulling this info from the database, it is pulling the correct total amount of clicks but the last_updated field is from the first row (yesterday) not the new row inserted today.
How can I go about getting the most recent last_updated field?

If you want the most recent date, use MAX to select it:
SELECT SUM(total_clicks) as clicks, MAX(last_updated) AS last_updated
FROM reporting
WHERE unique_id = 'xH7'
The problem with your version is that ORDER BY happens after aggregating, and aggregation selects non-aggregate columns from arbitrary rows in the table.

If you have only one row per day, then you don't need sum(). Does the following do what you want?
SELECT `total_clicks` AS clicks, `last_updated`
FROM `reporting`
WHERE `unique_id` = 'xH7'
ORDER BY `last_updated` DESC
LIMIT 1;
Your query is an aggregation query that adds up all the clicks in the table. Because it returns only one row, the order by isn't doing anything.

Related

Select records randomly and different from previously selected records

I have a table with 8,000 Records, I want to select randomly some records (for example 10) from this table. These records have to be different from previously selected records.
For example with this query I select some questions:
SELECT coloumn1,column2 FROM `myTable` WHERE `status`=1 AND `group`=6 ORDER BY RAND() LIMIT 0, :max
Now how can I select new records randomly and different from previously selected records?
Simply you could store the id's of previously selected records and then add to your next query like below, to avoid selecting them twice:
WHERE id NOT IN = (list of ids)
Based on you'r example:
SELECT coloumn1,column2 FROM `myTable` WHERE `status`=1 AND `group`=6 AND id NOT IN (_IDS_) ORDER BY RAND() LIMIT 0
try :
SELECT coloumn1, column2 FROM myTable WHERE status=1 AND group=6
AND coloumn1 NOT IN (id,id,id,id,ids concatenated in php)
ORDER BY RAND() LIMIT 0, :max
and also in select, better select a column that is unique identifier for the row, and use that column with the NOT IN ()
avoid RAND() as its extremely slow - better work around it with php
If the number of selected records is too big, put them in a temp table, and use
NOT IN (SELECT id FROM temp table...)

How to select from last to first row in mysql

Whenever a query like
"select * from table where userid=xx" is done, the mysql fetches these values from
first row to last row of table.
But I want to select from last to first so that recently updated values are displayed first in the results.
I cannot do "select * from table where userid=xx order by time DESC" because there is no time column in table.
I just want recently updated items in the table displayed first.
$result= mysql_query("SELECT
(SELECT column FROM table WHERE [condition] ORDER BY column LIMIT 1) as 'first',
(SELECT column FROM table WHERE [condition] ORDER BY column DESC LIMIT 1) as 'last'");
$row=mysql_fetch_array($result);
echo $row['first'];
echo $row['last'];
If you have any auto-incrementing field you could sort by that desc.
You must provide a column to order by in order to guarantee results. So you will have to either change your table structure or make a decision on what to order by.
A hack would be to pull in the data in the order presented into an array, then start popping off the bottom of that array.
You either have to have a timestamp, or autoincrement id, or some other column that you want to sort by.
Just because you get rows in a certain order from a database when not using an ORDER BY clause, does not mean that they are guaranteed to be returned in that order. It also doesn't imply any order in the result set. You need a definitive field that you can use to ORDER BY, or you cannot do what you are wanting to do.
Some hack you can do for that if you don't have columns you can rely on:
SELECT * FROM (SELECT *,(#x:=#x+1) default_ordering FROM `table_name`, (SELECT #x:=0) t2) any_name ORDER BY default_ordering DESC

MySQL optimization - Delete on certain count

I'm building a chat for a turn-based game (using PHP and MySQL) where I only want to save the 30 most recent messages in the MySQL database.
Currently, I'm doing 3 queries to delete the oldest message when the count exceeds 30:
Insert the new chat message as a new row:
INSERT INTO chatMessages (userId,matchId,message,timestamp) VALUES (".$params["userId"].",".$params["matchId"].",'".$params["message"]."',NOW())
Check if there are too many messages in the database, and get the oldest one's Id.
SELECT COUNT(id) AS count, id AS oldestId FROM chatMessages WHERE matchId = ".$params["matchId"]." ORDER BY id ASC LIMIT 1
Remove the oldest message
DELETE FROM chatMessages WHERE id = ".$oldestId
Is there any way to do this in 2, or even 1 single query? We have quite a lot of traffic on our servers, so performance is key.
You can reduce the 2nd and 3rd query to one:
delete from chatMessages
where id not in (select id from chatMessages
order by id desc
limit 30)
You could put that in an insert trigger. That way oldest records would get deleted automatically after an insert.

How to select the most recent 10 records

I have a mysql database. How do I select the most recent 10 records? Im not storing timestamps. But the most the recent records are the ones at the bottom rite? Also. How so I get the next ten , the next ten and so on on clicking a button. Kinda like a bunch of forum posts. The recent ones show up first.
I believe you have an auto increment column as a primary key you can use this column and to order by desc
select * from table order by id desc limit 10
otherwise you have a very poor database design
If you have an AUTO_INCREMENT column you can order by that in descending order then limit by 10.
But I suggest you store timestamps and order by that instead so you know you're sorting your records according to date, and not some other value that coincides with date of insertion.
In addition to what #BoltClock mentioned, prequerying the maximum ID might help the engine with what other records are retrieved... ie: if you have a million records, and most recent 10, I don't know if it will still try to query out the million, order them, and THEN dump it.. I would try something like
select STRAIGHT_JOIN
YT.*
from
( select max( IDColumn ) as MaxOnFile
from YourTable ) PreQuery,
YourTable YT
where
YT.IDColumn >= PreQuery.MaxOnFile -10
order by
YT.IDColumn DESC
limit 10
However, if for some reason, records are allowed to be deleted, you may opt to subtract a little farther back than the -10... but at least this way, the system won't even TRY to process all the other records...

PHP - MySQL display highest ID number

What SQL query would I use to display the newest entry?
Details:
id is the primary field. I have other fields but that are not related to when they were added.
ORDER BY SomeColumn DESC
LIMIT 1
or
use the MAX() function
Since you didn't give any details about your table it is hard to answer
SELECT * from yourTable ORDER BY `id` DESC LIMIT 1;
Another (better) way would be to have a "date_added" column (date_added TIMESTAMP DEFAULT CURRENT_TIMESTAMP) so you could order by that column descending instead. Dates are more reliable than ID-assignment.
not sure if this is what your looking for but I use mysql_insert_id() after inserting a new row
The auto incremented ID columns are not always the latest records inserted, I've remember really painful experience with this behavior. Conditions where specific, it was mysql 4.1.x at the time and there was almost 1 million records, where 1 out of 3 deleted everiday, and others re inserted in the next 24hours. It made a huge mess when I realize ordering them via ID was not ordering them by age....
Since then, I use a specific column for doing age related sorts, and populating these fields with date = NOW() at each row insert.
Of course it will work to found the latest record as you want, doing an ORDER BY date DESC LIMIT 0,1on your query
SELECT Primary_Key_Field FROM table ORDER BY Primary_Key_Field DESC LIMIT 1
Replace Primary_Key_Field and table obviously :)

Categories