mysql get the sum of unique date - mysql

From MySQL table I have the list amount based on the dates. I need to get the sum of amount for each date:
ex:
id type date amount
1 1 2015-01-01 100
2 1 2015-01-01 150
3 1 2015-01-02 10
4 1 2015-01-03 250
Here 2015-01-01 appears more than once.
so i need the result like
date amount
2015-01-01 200
2015-01-02 10
2015-01-03 250
My Query getting between this week start and end
SELECT * from mytable WHERE YEARWEEK(`date`) = YEARWEEK(CURRENT_DATE) AND `type` = 1 ORDER BY `date` ASC

You need a group by clause:
SELECT `date`, SUM(amount)
FROM mytable
GROUP BY `date`

I think the result should be
date amount
2015-01-01 250
2015-01-02 10
2015-01-03 250
you can use this mysql query to get that result:
Select date, sum(amount) as amount
from mytable
GROUP BY date
ORDER BY date asc
dont forget to add "ORDER BY" clause if you want the result in good order

Use GROUP BY
Use AS clause to change the column Name
SELECT `date`, SUM(amount) AS amount
FROM mytable
GROUP BY `date`

Related

How can I ignore duplicate values in another column when using GROUP?

I have the following query:
SELECT
DATE(`timeStamp`),COUNT(*)
FROM
`wf`.sh`
WHERE
(DATE(`timeStamp`) >= curdate()- INTERVAL 31 DAY)
GROUP BY
DATE(`timeStamp`)
HAVING
COUNT(DATE(`timeStamp`)) > 0
ORDER BY
DATE(`timeStamp`) ASC;
The purpose of this query is to retrieve the amount of users online in my system per day, in the space of a month.
Example dataset:
uID timeStamp
1 2016-11-28 00:27:01
1 2016-11-28 01:10:15
1234 2016-11-28 02:50:00
2 2016-11-28 06:11:09
47 2016-11-28 08:32:48
1246 2016-11-28 09:51:47
In its current format, this query returns the count of rows with duplicate dates, for example:
timeStamp COUNT(*)
2017-01-29 256
2017-01-30 224
2017-01-31 240
2017-02-01 95
2017-02-02 136
I have another field uID; I need to modify my query so that GROUP also ignores rows with a duplicate uID field for each day. I tried creating another GROUP BY but was given an error that 'incorrect GROUP BY clause' (or something of that nature).
Can this be done via pure MySQL?
You can use a subselect
SELECT
visitDate,COUNT(*)
FROM
(SELECT DISTINCT DATE(`timeStamp`) as visitDate, uID FROM `wf`.sh`) alias_t
WHERE
(visitDate >= curdate()- INTERVAL 31 DAY)
GROUP BY
visitDate
HAVING
COUNT(visitDate) > 0
ORDER BY
visitDate ASC;

SQL - How to order by min date

I have a table with logs
PERSON ID LOGDATE (DATETIME)
1000 2015-10-20 10:00:00
1000 2015-11-11 09:10:22
2001 2015-10-11 10:22:11
I need to order the data by LOGDATE -DATETIME - but with only the lowest date for each ID.
select PERSONALID, LOGDATE from TABLE group by PERSONALID order by
MIN(LOGDATE) DESC
I can GROUP by ID - ORDER BY Min DATE (each result by ID), but THE FINAL RESULT doesnt order the results by MIN DATE..
RESULT:
1000 ------------- 2015-10-20 10:00:00 (min date for ID=1000)
2001 ------------- 2015-10-11 10:22:11 (min date for ID=2001)
the right answer is:
RESULT:
2001 ------------- 2015-10-11 10:22:11 (min date for ID=2001)
1000 ------------- 2015-10-20 10:00:00 (min date for ID=1000)
what is wrong?
This should do it:
select PERSONALID, MIN(LOGDATE) as mindate
from TABLE
group by PERSONALID
order by mindate
You need to select MIN(LOGDATE), not LOGDATE. Selecting LOGDATE causes MySQL to return the value of an indeterminate record from within each group—see MySQL Handling of GROUP BY for more information.

Difference over sums in SQL

I have a table like the following:
PARENTREF TRANSTYPE(BIT(1)) DUEDATE(DateTime) TOTAL
2038 0 2015-01-01 1000
2038 1 2015-03-05 500
2039 0 2015-01-01 1000
2040 0 2015-01-01 1000
2041 0 2015-01-01 1000
2040 1 2015-04-07 200
I want a SELECT query that returns SUM(TOTAL) when TRANSTYPE=1 subtracted from SUM(TOTAL) when TRANSTYPE=0 for each distinct PARENTREF. I also would like to get in a separate column the DUEDATE for the PARENTREF when TRANSTYPE=0. There may be only one PARENTREF with TRANSTYPE=0 so that won't be a problem. In other words, I should get the following table:
PARENTREF DUEDATE(DateTime) TOTAL
2038 2015-01-01 500
2039 2015-01-01 1000
2040 2015-01-01 800
2041 2015-01-01 1000
(1-transtype*2) is 1 when transtype=0 and is -1 when transtype=1, so query subtract values of total where transtype=1 from value of total where transtype=0. max ignore null values, so it select only not null value where transtype=0.
select
parentref,
sum((1-transtype*2)*total) as total,
max(if(transtype=0,duedate,null)) as duedate
from tablename
group by parentref
Try this....
select t.PARENTREF,t.DueDate,(t.Total-isnull(m.Total,0)) as total
from tabl t LEFT outer join tabl m on t.PARENTREF=m.PARENTREF and t.TRANSTYPE <> m.TRANSTYPE
where (t.Transtype=0 ) and (isnull(m.Transtype,1)=1 )
Please Check out this fiddle http://sqlfiddle.com/#!3/d4988/1
or use thiss...
select t.PARENTREF,t.DueDate,(sum(t.Total)-sum(isnull(m.Total,0))) as total
from tabl t LEFT outer join tabl m on t.PARENTREF=m.PARENTREF and t.TRANSTYPE <> m.TRANSTYPE
where (t.Transtype=0 ) and (isnull(m.Transtype,1)=1 )
group by t.PARENTREF,t.DueDate
Check this fiddle http://sqlfiddle.com/#!3/d4988/2

Given a table with time periods, query for a list of sum per day

Let's say I have a table that says how many items of something are valid between two dates.
Additionally, there may be multiple such periods.
For example, given a table:
itemtype | count | start | end
A | 10 | 2014-01-01 | 2014-01-10
A | 10 | 2014-01-05 | 2014-01-08
This means that there are 10 items of type A valid 2014-01-01 - 2014-01-10 and additionally, there are 10 valid 2014-01-05 - 2014-01-08.
So for example, the sum of valid items at 2014-01-06 are 20.
How can I query the table to get the sum per day? I would like a result such as
2014-01-01 10
2014-01-02 10
2014-01-03 10
2014-01-04 10
2014-01-05 20
2014-01-06 20
2014-01-07 20
2014-01-08 20
2014-01-09 10
2014-01-10 10
Can this be done with SQL? Either Oracle or MySQL would be fine
The basic syntax you are looking for is as follows:
For my example below I've defined a new table called DateTimePeriods which has a column for StartDate and EndDate both of which are DATE columns.
SELECT
SUM(NumericColumnName)
, DateTimePeriods.StartDate
, DateTimePeriods.EndDate
FROM
TableName
INNER JOIN DateTimePeriods ON TableName.dateColumnName BETWEEN DateTimePeriods.StartDate and DateTimePeriods.EndDate
GROUP BY
DateTimePeriods.StartDate
, DateTimePeriods.EndDate
Obviously the above code won't work on your database but should give you a reasonable place to start. You should look into GROUP BY and Aggregate Functions. I'm also not certain of how universal BETWEEN is for each database type, but you could do it using other comparisons such as <= and >=.
There are several ways to go about this. First, you need a list of dense dates to query. Using a row generator statement can provide that:
select date '2014-01-01' + level -1 d
from dual
connect by level <= 15;
Then for each date, select the sum of inventory:
with
sample_data as
(select 'A' itemtype, 10 item_count, date '2014-01-01' start_date, date '2014-01-10' end_date from dual union all
select 'A', 10, date '2014-01-05', date '2014-01-08' from dual),
periods as (select date '2014-01-01' + level -1 d from dual connect by level <= 15)
select
periods.d,
(select sum(item_count) from sample_data where periods.d between start_date and end_date) available
from periods
where periods.d = date '2014-01-06';
You would need to dynamically set the number of date rows to generate.
If you only needed a single row, then a query like this would work:
with
sample_data as
(select 'A' itemtype, 10 item_count, date '2014-01-01' start_date, date '2014-01-10' end_date from dual union all
select 'A', 10, date '2014-01-05', date '2014-01-08' from dual)
select sum(item_count)
from sample_data
where date '2014-01-06' between start_date and end_date;

MySQL Selecting MAX total with date and ID

I have a cron script that writes the total number of active users to a table every day. I'm trying to now generate a simple report that would show the "high water mark" for each month. Because some accounts expire during the month it's possible the highest number may NOT be at the end of the month.
Here's a sample of my table structure
tblUserLog
-----------
record_id INT(11) // PRIMARY KEY
run_date DATE // DATE RUN
ttl_count INT(11) // TOTAL FOR DAY
Sample data:
record_id run_date ttl_count
1 2013-06-01 500
2 2013-06-10 510
3 2013-06-20 520
4 2013-06-30 515
5 2013-07-01 525
6 2013-07-10 530
7 2013-07-20 540
8 2013-07-31 550
9 2013-08-01 560
What I would like returned is:
record_id run_date ttl_count
3 2013-06-20 520
8 2013-07-31 550
9 2013-08-01 560
I've tried two queries that are close...
// This will give me the total for the first of the month
SELECT s.record_id, s.run_date, s.ttl_count
FROM tblStatsIndividual s
JOIN (
SELECT record_id
FROM tblStatsIndividual
GROUP BY DATE_FORMAT(run_date, '%Y %m')
HAVING MAX(ttl_count)
) s2
ON s2.record_id = s.record_id
ORDER BY run_date DESC
This returns the total for the first of each month, along with the record_id and correct date for the total.
Tried this...
SELECT record_id,max(run_date), max(ttl)
FROM (
SELECT record_id,run_date, max(ttl_count) AS ttl
FROM tblStatsIndividual
GROUP BY DATE_FORMAT(run_date, '%Y %m')
) a
GROUP BY DATE_FORMAT(run_date, '%Y %m')
ORDER BY run_date DESC
This one appears to get the correct "high water mark" but it's not returning the record_id, or the run_date for the row that IS the high water mark.
How do you get the record_id and the run_date for the highest total?
Something like
Select detail.Record_ID, detail.Run_Date, detail.ttl_Count
From tblStatsIndividual detail
Inner Join
(Select Year(run_date) as Year, Month(Run_date) as Month, Max(ttl_count) as ttl
From tblStatsIndividual
Group By Year(run_date), Month(Run_date)) maximums
On maximums.Year = Year(detail.Run_date) and maximums.Month = Month(detail.Run_date)
and maximums.ttl = detail.ttl_count
Should do it. NB based on your requirement if you had two records in the same month with the same (and highest in the month) ttl_count, they would both be returned.
Based on the help from #Tony Hopkinson, This query gets me the info. The one caveat is it shows the ID and date for the first occurrence of the MAX total, so if the total is the same three days in a row on a month, the first day's ID is returned. For my purpose, the last ID would be more ideal, but I can live with this:
SELECT s.Record_ID, s.Run_Date, s.ttl_Count
FROM tblStatsIndividual s
INNER JOIN (
SELECT YEAR(run_date) AS yr, MONTH(run_date) AS mon, MAX(ttl_count) AS ttl
FROM tblStatsIndividual
GROUP BY DATE_FORMAT(run_date, '%Y %m')
) maximums
ON maximums.yr = YEAR(s.run_date)
AND maximums.mon = MONTH(s.run_date)
AND maximums.ttl = s.ttl_Count
GROUP BY ttl_count
ORDER BY run_date DESC