Selecting Dates to sql and Sum - php

Good day. I am Selecting Dates to MYSql and I select it one by one. I want to select all one week. And I used to select it individually.
Here is my code:
<?php
$chart6 = $controller->runQuery("SELECT SUM(amount) FROM tbl_paid WHERE pay_date >= :today - INTERVAL 6 DAY");
$chart6->execute(array(":today"=>$today));
$chartData6 = $chart6->fetchColumn();
$chart5 = $controller->runQuery("SELECT SUM(amount) FROM tbl_paid WHERE pay_date >= :today - INTERVAL 5 DAY");
$chart5->execute(array(":today"=>$today));
$chartData5 = $chart5->fetchColumn();
$chart4 = $controller->runQuery("SELECT SUM(amount) FROM tbl_paid WHERE pay_date >= :today - INTERVAL 4 DAY");
$chart4->execute(array(":today"=>$today));
$chartData4 = $chart4->fetchColumn();
$chart3 = $controller->runQuery("SELECT SUM(amount) FROM tbl_paid WHERE pay_date >= :today - INTERVAL 3 DAY");
$chart3->execute(array(":today"=>$today));
$chartData3 = $chart3->fetchColumn();
$chart2 = $controller->runQuery("SELECT SUM(amount) FROM tbl_paid WHERE pay_date >= :today - INTERVAL 2 DAY");
$chart2->execute(array(":today"=>$today));
$chartData2 = $chart2->fetchColumn();
$chart1 = $controller->runQuery("SELECT SUM(amount) FROM tbl_paid WHERE pay_date >= :today - INTERVAL 1 DAY");
$chart1->execute(array(":today"=>$today));
$chartData1 = $chart1->fetchColumn();
$chart0 = $controller->runQuery("SELECT SUM(amount) FROM tbl_paid WHERE pay_date >= :today");
$chart0->execute(array(":today"=>$today));
$chartData0 = $chart0->fetchColumn();
?>
Is there query that can select the sum of the whole day of the week? or I should keep this code?

try it sql use group
SELECT Day(pay_date) pay_day,SUM(amount) amount
FROM tbl_paid WHERE pay_date >= NOW() - INTERVAL 6 DAY
GROUP BY Day(pay_date)
result:
| pay_day | amount |
|---------|--------|
| 1 | 246 |
| 2 | 200 |
| 28 | 1702 |
| 29 | 1462 |
| 30 | 864 |
| 31 | 1092 |
Test Data :
| amount | pay_date |
|--------|----------------------|
| 100 | 2018-06-02T00:00:00Z |
| 123 | 2018-06-01T00:00:00Z |
| 546 | 2018-05-31T00:00:00Z |
| 432 | 2018-05-30T00:00:00Z |
| 731 | 2018-05-29T00:00:00Z |
| 851 | 2018-05-28T00:00:00Z |
| 100 | 2018-06-02T00:00:00Z |
| 123 | 2018-06-01T00:00:00Z |
| 546 | 2018-05-31T00:00:00Z |
| 432 | 2018-05-30T00:00:00Z |
| 731 | 2018-05-29T00:00:00Z |
| 851 | 2018-05-28T00:00:00Z |
| 436 | 2018-05-27T00:00:00Z |
SQL Fiddle Demo Link
if you want more information then
you can use weekday() and DAYNAME()
SELECT WEEKDAY(pay_date) WEEKDAY,DAYNAME(pay_date) DAYNAME,SUM(amount) amount
FROM tbl_paid WHERE pay_date >= NOW() - INTERVAL 7 DAY
GROUP BY WEEKDAY(pay_date),DAYNAME(pay_date)
result:
| WEEKDAY | DAYNAME | amount |
|---------|-----------|--------|
| 0 | Monday | 1702 |
| 1 | Tuesday | 1462 |
| 2 | Wednesday | 864 |
| 3 | Thursday | 1092 |
| 4 | Friday | 246 |
| 5 | Saturday | 200 |
| 6 | Sunday | 1287 |
SQL Fiddle Demo Link

If you must pass the date then do:
SELECT DATE(pay_date) `DATE`, SUM(amount) daily_amount
FROM tbl_paid
WHERE DATE(pay_date) BETWEEN DATE(:today) - INTERVAL 1 WEEK AND DATE(:today)
GROUP BY DATE(pay_date);
Else use the current date of the database.
SELECT DATE(pay_date) `DATE`, SUM(amount) daily_amount
FROM tbl_paid
WHERE DATE(pay_date)>=CURRENT_DATE - INTERVAL 1 WEEK
GROUP BY DATE(pay_date);
You don't need to run the query seven times. Remember; don't repeat yourself (DRY).

Related

DATETIME value missing in query output then autofill that missing values and get correct output

When I take the data from a database with a one-second interval that time only available DateTime interval output count gets and missing some DateTime interval from the output.
I fill all missing DateTime intervals with count 0.
Example:
if start date: 2019-10-15 02:36:23 then
end date : 2019-10-15 03:36:22
get one-hour data with one-second intervals if that time not available any count then get 0 counts.
mysql> select start_date,count(id) as count from live_login where start_date >= '2019-10-15 02:36:23' GROUP BY UNIX_TIMESTAMP(start_date) DIV 1;
+---------------------+-------+
| start_date | count |
+---------------------+-------+
| 2019-10-15 02:36:23 | 1 |
| 2019-10-15 02:36:24 | 1 |
| 2019-10-15 02:36:26 | 1 |
| 2019-10-15 02:36:55 | 1 |
| 2019-10-15 02:36:57 | 1 |
| 2019-10-15 02:37:08 | 1 |
Output need like this:
| start_date | count |
+---------------------+-------+
| 2019-10-15 02:36:23 | 1 |
| 2019-10-15 02:36:24 | 1 |
| 2019-10-15 02:36:25 | 0 |
| 2019-10-15 02:36:26 | 1 |
| 2019-10-15 02:36:27 | 0 |
| 2019-10-15 02:36:28 | 0 |
| 2019-10-15 02:36:29 | 0 |
| 2019-10-15 02:36:30 | 0 |
| 2019-10-15 02:36:31 | 0 |
| 2019-10-15 02:36:32 | 0 |
| 2019-10-15 02:36:33 | 0 |
| 2019-10-15 02:36:34 | 0 |
| 2019-10-15 02:36:35 | 0 |
You could make a virtual table containing all the seconds in the appropriate range, and then join them to the summary.
Try to modify the query like this :
SELECT COUNT(id) AS count,
listofseconds.login_date
FROM (
SELECT mintime + INTERVAL seq.seq SECOND AS login_date
FROM (
SELECT '2019-10-15 02:36:23' AS mintime,
(SELECT DATE_ADD('2019-10-15 02:36:23', INTERVAL '59:59' MINUTE_SECOND)) AS maxtime
FROM live_login
) AS minmax
JOIN seq_0_to_999999 AS seq ON seq.seq < TIMESTAMPDIFF(SECOND,mintime,maxtime)
) AS listofseconds
LEFT JOIN live_login ON listofseconds.login_date = SECOND(live_login.start_date)
GROUP BY SECOND(listofseconds.login_date)
ORDER BY SECOND(listofseconds.login_date)
This query will get an end_date of 2019-10-15 03:36:22 :
SELECT DATE_ADD('2019-10-15 02:36:23', INTERVAL '59:59' MINUTE_SECOND)
This query will get the seconds in the range :
SELECT mintime + INTERVAL seq.seq SECOND AS login_date
FROM (
SELECT '2019-10-15 02:36:23' AS mintime,
(SELECT DATE_ADD('2019-10-15 02:36:23', INTERVAL '59:59' MINUTE_SECOND)) AS maxtime
FROM live_login
) AS minmax
JOIN seq_0_to_999999 AS seq ON seq.seq < TIMESTAMPDIFF(SECOND,mintime,maxtime)

How to classify a few time-stamp according to identical days?

I have a table like this:
// Times
+----+-------------+
| id | timestamp | // echo date('d/m/Y', $time)
+----+-------------+
| 1 | 1448460315 | // 25/11/2015 -- today
| 2 | 1428440265 | // 07/04/2015
| 3 | 1418160365 | // 09/12/2014
| 4 | 1448460215 | // 25/11/2015 -- today
| 5 | 1438440265 | // 01/08/2015
| 6 | 1438340265 | // 31/07/2015
| 7 | 1438437265 | // 01/08/2015
| 8 | 1448370315 | // 24/11/2015 -- yesterday
| 9 | 1148370315 | // 23/05/2006
| 10 | 1447870315 | // 18/11/2015 -- last week ({11-18}/11/2015)
+----+-------------+
Note: All those number in timestamp column are made of time() function using PHP.
Now I want to know, how can I select all rows which are today Or all rows which are yesterday, or last week?* (it should be noted, in MySQL NOW() is the same with time()).*
For example:
// Times - Today
+----+-------------+
| id | timestamp | // echo date('d/m/Y', $time)
+----+-------------+
| 1 | 1448460315 | // 25/11/2015 -- today
| 4 | 1448460215 | // 25/11/2015 -- today
+----+-------------+
You would need to use the MySQL BETWEEN function
use PHP to get the timestamp from midnight of day to 11:59:59 of day
date_default_timezone_set('America/Chicago');
$day_begins = strtotime(date('Y-m-d 00:00:00', strtotime('today')));
$day_ends = strtotime(date('Y-m-d 11:59:59', strtotime('today')));
-- sql code will look like
SELECT id FROM table WHERE `timestamp` BETWEEN ($day_begins AND $day_ends)
With something like:
SELECT
id,
timestamp
FROM
table
WHERE
DATE_FORMAT(FROM_UNIXTIME(`timestamp`), '%y-%m-%d') = (DATE_FORMAT(NOW(), '%y-%m-%d') - INTERVAL 1 DAY)

Fetching last 30 days data from mysql table and grouping them by date

Here is how my table looks like
| total_hit |success_hit | date_time |
| 12 | 12 | 01-11-2009 07:32:44 |
| 12 | 11 | 01-11-2009 08:33:49 |
| 12 | 10 | 01-11-2009 09:08:24 |
| 12 | 11 | 01-12-2009 10:33:57 |
| 12 | 12 | 01-12-2009 11:37:34 |
| 12 | 11 | 01-12-2009 12:23:49 |
I am fetching the data from the table for the past 30 days using the following query:
SELECT *
FROM my_table
WHERE DATE(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
what I want to do is group the returned data in terms of date and calculate the percentage success (success_hit/total_hit)*100
Something like
Date: 01-11-2009 Percentage: x
Date: 01-12-2009 Percentage: y
any ideas?
select (success/total)*100 as perc_success, Date(date_time) from
(select sum(success_hit) as success, sum(total_hit) as total,
date_time from my_table
where DATE(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
group by Date(date_time) )
tbl
This should work!!!
Try this
SELECT (sum(success_hit)/sum(total_hit)*100) AS `Percentage`,
DATE(date_time) AS `Date`
FROM my_table
WHERE DATE(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
GROUP BY DATE(date_time);

mysql month wise report

I need an output like this:
Month -->| Pre_Mnth2 | Pre_Mnth1 | current_Month_ Name
Product A | 3387 | 87985 | 2338
Product B | 6386 | 67983 | 6374
Product C | 3880 | 76988 | 9378
...
All the required data is in single table only.
Column looks like this:
id | companycode | merchantcode| pdtname | qty | value | invdate |
Can anybody help me with php mysql query code?
My current code returns the data for current month only
SELECT `pdtname`, `qty`, `value`, sum(`qty`), sum(`value`)
FROM `ist`
WHERE merchantcode = $q AND companycode = $companycode
AND MONTH(invdate) = $currentdate[mon]
GROUP BY `pdtname`
Here variable $q and $companycode is taken from user session.
Are you looking for something like this?
SELECT pdtname,
SUM(CASE WHEN invdate
BETWEEN LAST_DAY(CURDATE()) - INTERVAL 3 MONTH + INTERVAL 1 DAY
AND LAST_DAY(CURDATE()) - INTERVAL 2 MONTH THEN qty END) qty_2m,
SUM(CASE WHEN invdate
BETWEEN LAST_DAY(CURDATE()) - INTERVAL 3 MONTH + INTERVAL 1 DAY
AND LAST_DAY(CURDATE()) - INTERVAL 2 MONTH THEN value END) value_2m,
SUM(CASE WHEN invdate
BETWEEN LAST_DAY(CURDATE()) - INTERVAL 2 MONTH + INTERVAL 1 DAY
AND LAST_DAY(CURDATE()) - INTERVAL 1 MONTH THEN qty END) qty_1m,
SUM(CASE WHEN invdate
BETWEEN LAST_DAY(CURDATE()) - INTERVAL 2 MONTH + INTERVAL 1 DAY
AND LAST_DAY(CURDATE()) - INTERVAL 1 MONTH THEN value END) value_1m,
SUM(CASE WHEN invdate
BETWEEN LAST_DAY(CURDATE()) - INTERVAL 1 MONTH + INTERVAL 1 DAY
AND LAST_DAY(CURDATE()) THEN qty END) qty_m,
SUM(CASE WHEN invdate
BETWEEN LAST_DAY(CURDATE()) - INTERVAL 1 MONTH + INTERVAL 1 DAY
AND LAST_DAY(CURDATE()) THEN value END) value_m
FROM ist
WHERE invdate BETWEEN LAST_DAY(CURDATE()) - INTERVAL 3 MONTH + INTERVAL 1 DAY
AND LAST_DAY(CURDATE())
AND companycode = 1
AND merchantcode = 1
GROUP BY pdtname
Note: Make sure that you have an index on invdate.
Output:
| PDTNAME | QTY_2M | VALUE_2M | QTY_1M | VALUE_1M | QTY_M | VALUE_M |
|----------|--------|----------|--------|----------|-------|---------|
| ProductA | 30 | 3000 | 30 | 3000 | 30 | 3000 |
| ProductB | 100 | 1000 | 100 | 1000 | 100 | 1000 |
| ProductC | 320 | 3200 | 320 | 3200 | 320 | 3200 |
Here is SQLFiddle demo

Mysql select record that should have today and tomorrow date

I want to select record that must have two or more entries but should have today and tomorrow date in table. I am saving date in table in date format.
SELECT `availibility`.*
FROM (`availibility`)
WHERE `property_id`= 8818
AND (availibility.unavailibility_date between CURDATE()
AND DATE_ADD(CURDATE(),INTERVAL 1 DAY))
I am using above query but this will true even one date (today or tomorrow) exists. I want to get such record that should have both dates
for example
+---------+----------------+------------+
| ID | property_id | Date |
+---------+----------------+------------+
| 369516 | 8818 | 2013-01-19 |
| 369517 | 8818 | 2013-01-18 |
| 369518 | 8818 | 2013-01-17 |
| 418021 | 8818 | 2013-08-27 |
| 418022 | 8818 | 2013-08-28 |
| 418022 | 8818 | 2013-08-29 |
| 418022 | 2001 | 2013-07-29 |
| 418022 | 2001 |2013-07-30 |
+---------+----------------+------------+
8818 property should come in record set because both date exists here
SELECT property_id
FROM yourtable
WHERE date IN (CURDATE(), CURDATE() + INTERVAL 1 DAY)
GROUP BY property_id
HAVING COUNT(DISTINCT date)=2
Please see fiddle here.
You can use:
NOW() + INTERVAL 1 DAY
If you are only interested in the date, not the date and time then you can use CURDATE instead of NOW:
CURDATE() + INTERVAL 1 DAY
your query should be
SELECT `availibility`.*
FROM (`availibility`)
WHERE `property_id`= 8818
AND (availibility.unavailibility_date between CURDATE()
AND CURDATE() + INTERVAL 1 DAY // change here
Use a JOIN to make sure the second record exists:
SELECT `availibility`.*
FROM `availibility`
JOIN `availibility` AS availibility_tomorrow ON availibility_tomorrow.property_id = availibility.property_id AND availibility_tomorrow.unavailibility_date = DATE_ADD(CURDATE (),INTERVAL 1 DAY))
WHERE `property_id`= 8818 AND availibility.unavailibility_date = CURDATE()
If i have understood this good...
SELECT `property_id`, count(*) as no
FROM (`availibility`)
WHERE `property_id`= 8818
AND (availibility.unavailibility_date=CURDATE()
OR availibility.unavailibility_date=DATE_ADD(CURDATE(),INTERVAL 1 DAY))
having no =2

Categories