I got a database that registers user actions and their geolocation.
Now I would like to fetch this data at the hand of the last action per user.
The table looks a bit like:
geoaction_id AUTO INCREMENT
geoaction_user
geoaction_creationdate (Y-m-d H:i:s)
geoaction_action
geoaction_lon
geoaction_lat
Now I would like to make a simple query that selects of all users the last item.
But LIMIT 0,1 just parses one row no matter what. (LOGICALLY!!)
Group by gives a little better result.
But how to get only the last item per user?
Try this, please provide the queries you have checked out so far, in order to assist you better.
SELECT geoaction_user, geoaction_action
FROM table-name
GROUP BY geoaction_user
ORDER BY geoaction_action DESC LIMIT 1
Working with sets:
SELECT
g.geoaction_user,
g.geoaction_action,
g.geoaction_creationdate,
g.geoaction_lat,
g.geoaction_lon
FROM
(
SELECT
geoaction_user,
MAX(geoaction_id) max_id
FROM
geoactions
GROUP BY geoaction_user
) s
JOIN
geoactions g
ON s.geoaction_user = g.geoaction_user
AND s.max_id = geoaction_id
The subquery generates a virtual table with the geoaction_id from the latest entry in the tabble for each user_id, then the table is joined to get the data belong to the latest id.
If you need to filter out some records place the where clause in the subquery
Related
So I have the following query, which I use it to get some analytics stats.
SELECT count(*) as total,CONCAT(YEAR(created),'-',MONTH(created),'-',DAY(created))
as date_only FROM logs where action = 'banner view'
and created BETWEEN '2015-07-03 21:03'
AND '2017-08-02 21:03' group by date_only order by created asc
This works, and it gives me this:
So what I actually need is, the total count of the rows in this case is 20, this is a dummy example, but I need to use this count to check before showing the stats if the data is too big to be displayed on a graphic.
Can this be achieved?
//LE
So the process will be like this:
1. Get a count of the total rows, if the count of rows is smaller than X(number will be in config and it will be a basic if statement), then go ahread and run the above query.
More info:
I actually use this query to display the stats, I just need to adapt it in order to show the total count rows
So the result of thquery should be
total | 20 in this case
I think you would want to use a derived table. Just wrap your original query in parenthesis after the FROM and then give the derived table an alias (in this case tmp). Like so:
SELECT count(*) FROM (
SELECT count(*) as total,CONCAT(YEAR(created),'-',MONTH(created),'-',DAY(created))
as date_only FROM logs where action = 'banner view'
and created BETWEEN '2015-07-03 21:03'
AND '2017-08-02 21:03' group by date_only order by created asc
) as tmp;
If I understand what you want to do correctly, this should work. It should return the actual number of results from your original query.
What's happening is that the results of the parenthesized query are getting used as a sort of virtual table to query against. The parenthesized query returns 20 rows, so the "virtual" table has 20 rows. The outer count(*) just counts how many rows there are in that virtual table.
Based on the PHP tag, I assume you are using PHP to send the queries to MySQL. If so, you can use mysqli_num_rows to get the answer.
If your query result is in $result then:
$total = mysqli_num_rows($result);
Slightly different syntax for Object Oriented style instead of procedural style.
The best part is you don't need an extra query. You perform the original query and get mysqli_num_rows as an extra without running another query. So you can figure out pagination or font size or whatever and then display without doing the query again.
This is an small query but works fine, and give me the total number of rows, you just need add your conditions.
SELECT COUNT(*) FROM table WHERE field LIKE '%condition%'
The group by I think you need to eliminated, becouse, this instead of count the records, divide in all your group by, example: records = 4, with group by you have
1
1
1
1
I hope this help you
You can try this way .
SELECT COUNT(*) FROM ( SELECT count(*) as total,CONCAT(YEAR(created),'-',MONTH(created),'-',DAY(created))
as date_only FROM logs where action = 'banner view'
and created BETWEEN '2015-07-03 21:03'
AND '2017-08-02 21:03' group by date_only HAVING total >=20 ) temp
I want per day sales item count so for that one i already created query but it takes to much around 55.585s and query is
Query :
SELECT
td.db_date,
(
select count(*) from order as order where DATE(order.created_on) = td.db_date
)as day_contribute
FROM time_dimension as td
So can any one please let me know how may i optimized this query and reduce execution time.?
You can modify your query to join like:
SELECT
td.db_date, count(order.id) as day_contribute
FROM time_dimension as td
LEFT JOIN order ON DATE(order.created_on) = td.db_date
GROUP BY td.db_date;
I do not know your primary id key for table order - so used just "order.id". Replace it with your.
Also it is very important - test if you have index on td.db_date field.
And one more important thing - better to avoid using DATE(order.created_on). Because it is mean that DATE() method will be called each time when DB will compare dates. If it is possible - convert order.created_on to same format as td.db_date. Or join by other fields. That will add speed too.
First you should make sure you have index on created_on column in order table.
However if you have many records in time_dimension and many records in order table it might be hard to optimize the query, because for each record from time_dimension you need to search in order table.
You can also change count(*) into count(order_id) (assuming primary key in order table is order_id) or add extra column with date only in order table (created_on_date with date only and index on this column) so your query could look like this:
SELECT
td.db_date,
(
select count(order_id) from order where order.created_on_date = td.db_date
)as day_contribute
FROM time_dimension as td
However it's possible the execution time might be too high if you have many records in both tables, so it might be necessary to create one extra table where you hold number of orders for each day and update it in cron or when adding/updating/deleting records in order table
So far, I have taken 3 tables and joined them together. What I want to do is display the Last 100 entries (DESC) in ASC ORDER according to the timestamp in the column Posted.
This is as far as I could get: http://sqlfiddle.com/#!9/e2771/1
In addition, if there is a more efficient way to do this in PhP and not MYSQL, I'm all for that. I've tried looking, but haven't been able to find anything that works.
You just need one more level of sort:
select t.*
from (<your query here>) t
order by posted;
I have following tables
articles_category
id title sef_title
articles_data
id cat_id title sef_title details
On each table "id" is the primary key and articles_data.cat_id is foreign key of articles_category
I need to fetch one latest article data for each articles category with following data.
articles_category.id
articles_category.title
articles_category.sef_title
articles_data.id
articles_data.cat_id
articles_data.title
articles_data.sef_title
articles_data.details
I tried with following query but it displays first article (oldest entry) rather than latest one.
SELECT
articles_category.id as article_cat_id, articles_category.sef_title as cat_sef_title, articles_category.title as cat_title,
articles_data.id, articles_data.cat_id as listing_cat_id, articles_data.title, articles_data.sef_title, articles_data.details
FROM articles_category, articles_data
WHERE articles_category.id = articles_data.cat_id
GROUP BY articles_data.cat_id
ORDER BY articles_data.id DESC
if it's a one to many relation, try (untested):
SELECT *
FROM articles_category, articles_data
WHERE articles_category.id = articles_data.cat_id
AND articles_data.id in (
SELECT max(articles_data.id)
FROM articles_data GROUP BY cat_id
)
you are not guaranteed a particular row on a GROUP BY
and you should really use a date on your article as the max id is never guaranteed to be the latest article even if you are using autoincrement
ORDER affects the display of records after the GROUP function has been performed. The GROUP function recognizes the first record it sees in its search.
What you need to do is perform 2 queries. The first one should be
SELECT max(articles_data.id), articles_data.cat_id ...
GROUP BY articles_data.cat_id
The second query should fetch the associated records using those resultant primary keys.
A possibility is to create another value such as date_created and place a time stamp there when creating an entry.
Then you would just have to ORDER BY date.
I have a table of customers with a 1 recorded against their customerid on different dates.
I would like to find the sum of the 1's recorded in descending order. I'm using MySQL and php
Thanks
My guess is that you want the sum of records marked with 1 per customer and sort that result in descending order? If so, the following should do the trick :
select cust.id, sum(cone.one) as number_ones
from customers as cust
inner join customer_ones as cone on cone.id=cust.id
group by cust.id
order by number_ones desc
This is assuming that 'one' is the column containing ones (and only contains 0 or 1 - otherwise you will have to add WHERE cone.one = 1), customers is your customer table and customer_ones is the table containing your customer data.
As i get you right, this is simple sql request what u need:
SELECT COUNT(id) as total from customers
Just make in php:
$sql="SELECT COUNT(id) from customers";
$query=mysql_query($sql) or die(mysql_error());
$res=mysql_fetch_assoc($query);
$summ=$res['total']; //<- Your summ (i.e. quantity of rows in table)
Btw, you can use mysql_num_rows instead.
Or explain please more accurately what output you need. To make sorting by date or any other dependency you will need to make other request using WHERE clause and date comparison.