Get total of amount based on date - php

PaymentHistory Table
==========================
UserId | Amount | Date
==========================
1 | 300 | 2014-06-26
3 | 300 | 2014-06-26
2 | 200 | 2014-06-26
1 | 400 | 2014-06-22
1 | 100 | 2014-06-21
display two columns first is sum of amount as Named "currentEarning" which has same date of today and second is sum of amount as Named "oldEarning" based on previous date of today. (for particular userId) see output:
output
=====================================
UserId | currentEarning | oldEarning |
=====================================
1 | 300 | 500

You can do that with one query:
SELECT
SUM(IF(`Date` = CURRENT_DATE, AMOUNT, 0)) AS currentEarning,
SUM(IF(`Date` < CURRENT_DATE, AMOUNT, 0)) AS oldEarning
FROM PaymentHistory
GROUP BY `UserId`
Way more efficient than subqueries or two separate queries.

Get current amount:
SELECT UserId, SUM(Amount) as currentEarning, Date FROM PaymentHistory WHERE UserId = '1' AND DATE(Date) = CURDATE()
Get old amount:
SELECT UserId, SUM(Amount) as oldEarning, Date FROM PaymentHistory WHERE UserId = '1' AND DATE(Date) != CURDATE()
This should work

SELECT `UserId`,
(SELECT SUM(`Amount`) FROM `PaymentHistory` WHERE `UserID` = t1.`UserId` AND `Date` = t1.`Date`) AS `currentEarning`,
(SELECT SUM(`Amount`) FROM `PaymentHistory` WHERE `UserID` = t1.`UserId` AND `Date` < t1.`Date`) AS `oldEarning`
FROM PaymentHistory AS t1
WHERE t1.`Date` = CURRENT_DATE
GROUP BY t1.`UserId`
HAVING `oldEarning` IS NOT NULL

Related

Executing two queries and exiting a unique table

I have a database, and I would like to get data where the username is equal to x and I would also like to get data regardless of the user.
I have the two queries:
SELECT MONTH(date) as month, COUNT(*) as count
from DB_NAME
WHERE YEAR(date) = YEAR(CURDATE()) AND userid = 'userid'
GROUP BY month
SELECT MONTH(date) as month, COUNT(*) as count
from DB_NAME
WHERE YEAR(date) = YEAR(CURDATE())
GROUP BY month
Expected output:
+-------+------+-----+
| month | user | all |
+-------+------+-----+
| 1 | 100 | 200 |
| 2 | 90 | 150 |
+-------+------+-----+
I think some conditional aggregation is what you are after here:
SELECT
MONTH(date) as month,
COUNT(CASE WHEN userid = 'userid' THEN 1 END) as user,
COUNT(*) as count
from DB_NAME
WHERE YEAR(date) = YEAR(CURDATE())
GROUP BY month;

SQL - Get multiple values when limit 1

If I have a table like this:
ID | ident | product
1 | cucu1 | 99867 |
2 | kkju7 | 88987 |
3 | sjdu4 | 66754 |
4 | kjhu6 | 76654 |
5 | cucu1 | 98876 |
And use this query: SELECT ident,COUNT(*) FROM sales WHERE status=? AND team=? AND DATE(date) = DATE(NOW() - INTERVAL 1 DAY) GROUP BY ident order by COUNT(*) DESC LIMIT 1
I get the value: cucu1, since that has the most rows.
But if my table is like this:
ID | ident | product
1 | cucu1 | 99867 |
2 | kkju7 | 88987 |
3 | sjdu4 | 66754 |
4 | kkju7 | 76654 |
5 | cucu1 | 98876 |
It should return both cucu1 and kkju7, since they are the highest with same count, but still it gives me only cucu1. What am I doing wrong?
You can use rank():
SELECT ident, cnt
FROM (SELECT ident, COUNT(*) as cnt,
RANK() OVER (ORDER BY COUNT(*) DESC) as seqnum
FROM sales
WHERE status = ? AND team = ? AND
DATE(date) = DATE(NOW() - INTERVAL 1 DAY)
GROUP BY ident
) i
WHERE seqnum = 1;
LIMIT keyword simply limits the results to 1 row, no matter if there are equal values before or after the returned row.
A better solution would be to select the rows which have a count that's equal to max count in the query, which can be achieved by the following query:
SELECT ident,COUNT(*)
FROM sales
WHERE status=?
AND team=?
AND DATE(date) = DATE(NOW() - INTERVAL 1 DAY)
GROUP BY ident
HAVING COUNT(*) = MAX(COUNT(*))

Select SUM "separately" for the past 30 days

I have a MySQL table which is as follows
------------------------------------------------
| id | user_id | day | value |
| INT(11) | INT(11) | INT(8) | DECIMAL(5,2) |
------------------------------------------------
Day is (Ymd) number like this: 20191012
I want to grab the SUM(value) for Today and the past 29 days separately (30 days, based on day column)
I thought of a loop like this
for($i=0;$i<=30;$i++)
{
$query = "SELECT SUM(value) FROM table WHERE day=".date('Ymd', strtotime("-{$i} days"));
}
But how can I achieve this more efficiently?
Any help is appreciated.
You could use Group By to fetch it with a single MySQL-Query
SELECT day, SUM(value) FROM table GROUP BY day WHERE day >= ".date('Ymd', strtotime("-29 days"));
It should work because your day field is a number and will increase everyday so you can just compare it with gte
Expected output will be
---------------------------
| day | SUM(value) |
| INT(8) | |
---------------------------
| 20191012 | 15.25 |
---------------------------
| 20191011 | 29.13 |
---------------------------
| ... | ... |
---------------------------
J4I: If there are days without values in your dataset, the missing "day-row" is also missing in the output so it could be that there are less than 30 result-rows.
This query will work for any version of MySQL. It creates a temporary numbers table with the numbers from 0-29, then uses that to compute a list of days from today to 29 days earlier. This is then LEFT JOINed to the data table to compute the sum per day, with 0 sums where there is no data for a given day:
SELECT d.day, COALESCE(SUM(value), 0)
FROM (SELECT DATE_FORMAT(CURDATE() -INTERVAL n10.n * 10 + n.n DAY, '%Y%m%d') AS day
FROM (SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6
UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) n
CROSS JOIN (SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2) n10) d
LEFT JOIN `table` t ON t.day = d.day
GROUP BY d.day
Demo on dbfiddle

Split date range and get combined results in mysql

I have two tables
orders_status_history
id | order_id | status | date
1 | 1201 | 2 | 2015-01-20
2 | 1124 | 4 | 2015-02-01
3 | 1245 | 1 | 2015-02-14
4 | 1365 | 2 | 2015-03-10
saved_shipping_invoices
id | order_id | product_id | date
1 | 1348 | 12541 | 2015-12-18
2 | 1298 | 11485 | 2016-01-02
3 | 1319 | 14521 | 2016-05-14
4 | 1441 | 10124 | 2016-05-14
and one year date range i.e.
$start_date = '2015-09-30';
$end_date = '2016-09-30';
Data in table "shipping_invoice_history" started from 2015-12-18. Now I want to break date interval on 2015-12-18. There will be two intervals now
$interval1_start = '2015-09-30';
$interval_end = '2015-12-17';
$interval2_start = '2015-12-18';
$interval2_end = '2016-09-30';
When it breaks the date interval, I want to get data from table "orders_status_history" on the first interval but on the second interval it gets data from "shipping_invoice_history" .Also I need to show the data in single table.
$week = '2015-09-30 ## 2016-09-30';
$week_ranges = explode('##', $week);
if ($week_ranges[0] > '2015-12-18' )
{
$invoices_shipped_qty = tep_db_query("SELECT * FROM `saved_shipping_invoices` WHERE `date_created` BETWEEN '".$week_ranges[0]."' AND '".$week_ranges[1]."'");
$invoices_shipped_arr = tep_db_fetch_array($invoices_shipped_qty);
$total_sent = $invoices_shipped_arr['shiped_qty'];
}
else {
$total_order_status_complete = tep_db_query("SELECT * FROM `orders_status_history` WHERE `orders_status_id` = '17' AND `date_added` BETWEEN '".$week_ranges[0]." 00:00:00' AND '".$week_ranges[1]." 23;59:59'");
$total_order_status_complete_arr = tep_db_fetch_array($total_order_status_complete);
Please suggest me how can i break date interval into two, get result from two tables and display in single run.
Probably this is what you want
select
'order_status_history' as table,
id,
order_id,
status,
null as product_id,
date from order_status_history
where
date between '2015-09-30' and '2015-12-17'
union all
select
'saved_shipping_invoices' as table,
id,
order_id,
null as status,
product_id,
date
from saved_shipping_invoices
where
date between '2015-12-18' and '2016-09-30'
Depending on how dynamic is your query, I like to do something like this instead of union.
I prefer this option:
select
if(date <='2015-12-17', 'Phase 1',
if(date >='2015-12-18', 'Phase 2',
'None')),
id,
order_id,
status,
null as product_id,
date from order_status_history
where
date between '2015-09-30' and '2016-09-30'
or
select
if(date between '2015-09-30' and '2015-12-17', 'Phase 1',
if(date between '2015-12-18' and '2016-09-30', 'Phase 2',
'None')),
id,
order_id,
status,
null as product_id,
date from order_status_history
where
date between '2015-09-30' and '2016-09-30'

How to fetch multiple duplicate value count in sql

i have database in which user device id and device registerd date (cr_date) stored i want to fetch list of total count of registerd devices on same day with date wise
Here below display table structure
device_ID | cr_date
--------------------
1 | 2016-06-02 18:02:13
2 | 2016-06-02 18:03:58
3 | 2016-06-02 18:04:11
4 | 2016-06-03 18:04:33
5 | 2016-06-03 18:04:33
6 | 2016-06-04 18:04:44
and i want below result
count | date
---------------------------------
3 | 2016-06-02
2 | 2016-06-03
1 | 2016-06-04
i used below query but dosent get success
SELECT device_type, count(*) AS duplicate_count
FROM (
SELECT device_type FROM tbl_app_deviceregister
GROUP BY device_type HAVING COUNT(device_type) > 0
) AS t
Did you want this;)
SELECT count(1) as `count`, date_format(cr_date, '%Y-%m-%d') as `date`
FROM tbl_app_deviceregister
GROUP BY `date`
ORDER BY `count` DESC
You should GROUP BY date value, not by device:
SELECT CAST(cr_date AS DATE) AS `date`, COUNT(device_id)
FROM tbl_app_deviceregister
GROUP BY CAST(cr_date AS DATE)
Your query doesn't seem to reference the same table structure that you've described, but from what I understand, would this work?
SELECT count(id), date_registered FROM (
SELECT
id,
DATE(FROM_UNIXTIME(cr_date)) as date_registered
FROM
tbl_app_deviceregister
) A GROUP BY date_registered
you group it by device_type which is wrong. try to group by date.
select COUNT(*) as count,CONVERT(date,cr_date) as date
from tbl_app_deviceregister
group by CONVERT(date,cr_date)

Categories