Combine 2 Mysql queries in to 1 (efficient way) - php

I have 2 tables:
The first contains data for the current day (per hour) - this table has raw data, that needs to be processed.
The second contains data for previous day (per day) - this table already has the values calculated for every day.
I want to combine this to rows in a MySQL query, so that I return the data for previous dates (per day) and for current day (again, per day).
Currently I am using 2 mysql queries:
//table 1, data for current day
$qry1="
select DATE_FORMAT(completedate,'%Y-%m-%d') as date, SUM(IF(complete = 1,affpayout,0)) as pay, COUNT(*) as leads
from leads
where affiliateid={$_SESSION["id"]} AND completedate>'$date'
GROUP BY DATE_FORMAT(completedate,'%Y-%m-%d')";
//table 2, data for previous days, already processsed, we just need to select it
$qry2="
select DATE(date) as date, affrevenue as pay, totalleads as leads
from leadsdays
GROUP BY DATE(date)";
How can I combine the 2 efficiently (speed performance is an issue)? What would be the best way to do this?

Try to UNION. Also, make sure your tables are indexed properly. Looks like you'll want completedate and affiliateid indexed at least. Not sure how much more efficient two queries is versus one union though...
$qry = "(select
DATE_FORMAT(completedate,'%Y-%m-%d') as `date`,
SUM(IF(complete = 1,affpayout,0)) as pay,
COUNT(*) as leads
from leads
where affiliateid={$_SESSION["id"]} AND completedate>'$date'
GROUP BY DATE_FORMAT(completedate,'%Y-%m-%d'))
UNION
(select
DATE(`date`) as `date`,
affrevenue as pay,
totalleads as leads
from leadsdays
GROUP BY DATE(`date`))
ORDER BY DATE(`date`)";

Related

Fast multi select MySQL and PHP

I'm searching for a method to query 2.704 MySQL selects in a fast way.
At the moment this queries need 202.91903 seconds, what is too slow.
What is the best way to do so many queries?
Why I need this?
I have 26 tables with entries from 24.11.2016 until today. Every minute there is a new entry. (time 10:00am until 04:00am - next day).
Now I need to select the newest entry of each day, but the latest entry could be at 04:00:00 but it also can be earlier (ex. 03:00 pm) I never know when the last entry was.
So I have following select:
SELECT `column1`, `column2`, `column3`
FROM `table`
WHERE `timestamp`>='2016-11-24 10:00:00' AND `timestamp`< '2016-11-25 04:01:00'
ORDER BY `id` DESC LIMIT 1
This select I make for every day and for every table.
Does anyone have a solution to speed this up?
create an index on your table for column timestamp. When your table rows is growing big, index will be require for it to search for your record fast. without index, it will be like you are searching for row 1 to the row you are looking for in million of rows.
Sample
create index index_name on table_name (column_name)
If i get you right...
I think you could change yours to this
SELECT `column1`, `column2`, `column3`
FROM `table`
WHERE date_format(`timestamp`,'%d/%m/%Y')=date_format(curdate(),'%d/%m/%Y')
ORDER BY `timestamp` DESC LIMIT 1
I am using timestamp and curdate() to select only the today records, order them by timestamp descending, so earlier will be on top and limit the rows to 1 so you will have only the earliest.

Mysql find dates using where in clause, or dates nearest to those in array

I have the following code and query:
//$month is an array of datetime objects
foreach($month as $key => $indMonth){
$formattedMonth[] = $month[$key]->format('Y-m-d');
}
$formattedMonths = implode("','",$formattedMonth);
$query = "SELECT id,date FROM table WHERE date in ('$formattedMonths') ORDER by date DESC";
The database holds dates for the past 450 days, but it is imperfect and there are some missing days. The point of the script is to retrieve data from the current day of the month and then the corresponding day on the five previous months, but I need a failsafe for when a date happens to be missing.
How can I modify this query so it picks either the date in the "where in" portion of the query or it finds the date nearest to that particular date in the array?
Is this best to do in the query, or am I better off returning a more complete data set, then using PHP to find out if the date I want is available?
MySQL offers some decent date arithmetic. For example, if you have the date '2015-11-10' (10-Nov-2015) you can get the same day three months prior with this expression:
'2015-11-10` - INTERVAL 3 MONTH
That will kick back '2015-08-10', which is what you want.
This date arithmetic works predictably even with longer and shorter months, and with leap years. For example,
'2015-03-31' - INTERVAL 1 MONTH, '2016-03-31' - INTERVAL 1 MONTH
gives back '2015-02-28', '2016-02-29' as you might expect. And
'2015-03-31' - INTERVAL 2 MONTH, '2016-03-31' - INTERVAL 2 MONTH
gives back '2015-03-31', '2016-03-31'. Perfect.
Now, only you can decide whether this predictable behavior is correct for your application: only you know what you want to do with the previous five months of data, when the day in question is near the end of the month.
Let's assume it's correct and move on. Here is a subquery that can be used to generate a sequence of six dates, one day per month ending today.
SELECT CURDATE() - INTERVAL seq.seq MONTH day_of_month
FROM ( SELECT 0 AS seq UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL
SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 6) seq
We can use this little query as a subquery, and LEFT JOIN it to your data. That would work like this:
SELECT id, day_of_month
FROM (
SELECT CURDATE() - INTERVAL seq.seq MONTH day_of_month
FROM ( SELECT 0 AS seq UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL
SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 6) seq
) days
LEFT JOIN table ON table.date = days.day_of_month
This is a cool way to do it because you'll always get at least one row in the resultset for each date in the list, even if there's nothing matching in table.
The closest date gets a little hairier. It's possible to write a query like that. But MySQL lacks a WITH clause so the query is ridiculously repetitive.

Daily usage time in Mysql database

I am trying to achieve the Sum of Hours spent per day, where my mysql database has multiple logging records of every activity they perform (e.g; login, view, update, logout). What i am trying to do is SELECT (all records of a particular day) and find the difference in epoch time between the first and last entry giving me the 'Time Spent' for that period. Later add it by Month etc.
Database schema;
id, userid, time, action
**I can select the first and last entry from the query below:
**
SELECT
(SELECT time FROM log WHERE time(myDate) = DATE(NOW()) ORDER BY time LIMIT 1) as 'first',
(SELECT column FROM table WHERE time(myDate) = DATE(NOW()) ORDER BY time DESC LIMIT 1) as 'last'
But i am guessing a cross join or SUM for all these have to happen. Some guidance would be much appreciated.

how to simplify this statement? php mysql

i need to retrieve multiple selects from mysql table, my need is to simplify the statements
these are my statements
$stardate=dateselect
$enddate=dateselect
SELECT count(distinct(customer)) as customer FROM my_table where date_field BETWEEN'$startdate' AND '$enddate'
SELECT count(distinct(customer)) as computeris1 FROM my_table where computer=1 and date_field BETWEEN'$startdate' AND '$enddate'
SELECT count(distinct(customer)) as computeris2 FROM my_table where computer=2 and date_field BETWEEN'$startdate' AND '$enddate'
I have about 10 fields, each one has 4 or 5 values (choices) want to count the distinct customer for each field (e.g. computer) and all between 2 dates..
another problem is the date is a timestamp of mysql, doesn't return a correct and exclude today's records unless i select the end date as tomorrow then it works, i think it is a time issue, how i can make it count date correctly discarding the time?
You can fix the date/time problem by using date(). As for the rest, you can use conditional aggregation to do everything in one query:
SELECT count(distinct(customer)) as customer,
count(distinct case when computer = 1 then customer end) as computer1,
count(distinct case when computer = 2 then customer end) as computer2
FROM my_table
where date(date_field) BETWEEN '$startdate' AND '$enddate';
This puts the values as separate columns rather than separate rows.

how to show one record per day order by id?

I have this little script that shows one wisdom each day.
so I have three columns.
Id wisdom timestamp
1 wisdon 1 4/1/2012
2 wisdon 2 4/1/2012
3 wisdon 3 4/2/2012
and I want to fetch array of one wisdom for each day
I looked around your website, but unfortunately I didn't find something similar to what I want.
also I got this code
$sql = mysql_query("SELECT DISTINCT id FROM day_table group by timestamp");
but this also not working.
any ideas?
is it possible to make a counter of 24 hours update wisdom date?
please give me some help.
You can make another table that is called wisdom_of_day
The table would have the following columns, id, wisdom_id, date
Basically each day you can randomly select a wisdom from your wisdom table and insert it into the wisdom day table. You can also add a constraint to your date column so it is distinct. It is important that it is a date column and not a timestamp since you don't care about time.
Then you can retrieve the wisdom of the day by querying based on the date.
It's possible I read your question wrong and you just want to select one wisdom for each day, but you want to show multiple days and you want to get the data from your table.
If so, the reason your query is not working is because you are grouping by a timestamp which includes the date and time. You need to group it by date for it to group like you want.
Here is a query that will group by the day correctly. This will only work if you have a timestamp field and are not storing a unix timstamp on an int column.
select id, wisdom, date(timestamp) date_only from day_table group by date_only order by date_only asc;
Hmm, I noticed that your timestamp values are in some kind of date format, maybe as a string? If so the above query probably won't work.
First compute number of days since 1970
SELECT DATEDIFF(CURDATE(), '1970-01-01')
Then insert this number inside RAND, for example:
SELECT * FROM table ORDER BY RAND(15767) LIMIT 1;
Rand with number as argument is deterministic.
Full query:
SELECT * FROM table ORDER BY RAND((SELECT DATEDIFF(CURDATE(), '1970-01-01'))) LIMIT 1;

Categories