SQL order by clause for 2 date columns - mysql

I have a table with a column named timestamp
i want to be able to order by month(timestamp) and year(timestamp) and group the months and years together
so for example, if i had the following timestamps:
2014-01-01
2014-02-01
2014-05-01
2015-01-01
i want to show in this order
MONTH YEAR
1 2015
5 2014
2 2014
1 2014

You can pick month and year from timestamp with MONTH and YEAR:
GROUP BY MONTH(field_with_ts) , YEAR(field_with_ts)
and the same thing with the ORDER BY clause.

Try this:
substring(date, 8 , 2) as Month, substring(date, 1, 3) as Year
See, if that works.

Related

MySQL Select data from table with dates between in reverse of interval 7 days

I have a MySQL requirement to select data from a table based on a start date and end date and group it by weekly also selecting the data in reverse order by date. Assume that, I have chosen the start date as 1st November and the end date as 04 December. Now, I would like to fetch the data as 04 December to 28 November, 27 November to 20 November, 19 November to 12 November and so on and sum the value count for that week.
Given an example table,
id
value
created_at
1
10
2021-10-11
2
13
2021-10-17
3
11
2021-10-25
4
8
2021-11-01
5
1
2021-11-10
6
4
2021-11-18
7
34
2021-11-25
8
17
2021-12-04
Now the result should be like 2021-12-04 to 2021-11-28 as one week, following the same in reverse order and summing the column value data for that week. I have tried in the query to add the interval of 7 days after the end date but it didn't work.
SELECT count(value) AS total, MIN(R.created_at)
FROM data_table AS D
WHERE D.created_at BETWEEN '2021-11-01' AND '2021-12-04' - INTERVAL 7 DAY ORDER BY D.created_at;
And it's also possible to have the last week may have lesser than 7 days.
Expected output:
end_interval
start_interval
total
2021-12-04
2021-11-27
17
2021-11-27
2021-11-20
34
2021-11-20
2021-11-13
4
2021-11-13
2021-11-06
1
2021-11-06
2021-10-30
8
2021-10-30
2021-10-25
11
Note that the last week is only 5 days depending upon the selected from and end dates.
One option to address this problem is to
generate a calendar of all your intervals, beginning from last date till first date, with a split of your choice, using a recursive query
joining back the calendar with the original table
capping start_interval at your start_date value
aggregating values for each interval
You can have three variables to be set, to customize your date intervals and position:
SET #start_date = DATE('2021-10-25');
SET #end_date = DATE('2021-12-04');
SET #interval_days = 7;
Then use the following query, as already described:
WITH RECURSIVE cte AS (
SELECT #end_date AS end_interval,
DATE_SUB(#end_date, INTERVAL #interval_days DAY) AS start_interval
UNION ALL
SELECT start_interval AS end_interval,
GREATEST(DATE(#start_date), DATE_SUB(start_interval, INTERVAL #interval_days DAY)) AS start_interval
FROM cte
WHERE start_interval > #start_date
)
SELECT end_interval, start_interval, SUM(_value) AS total
FROM cte
LEFT JOIN tab
ON tab.created_at BETWEEN start_interval AND end_interval
GROUP BY end_interval, start_interval
Check the demo here.

Mysql data fetch getting wrong time

i have some records on mysql db, i tried to group by month, data is correct but time of March month is showing as "2022-03-22", i required as same as other months like 2022-03-01.
time month_name inc_number
2022-01-04 19:58:09 January 39393
2022-02-08 17:36:33 February 90203
2022-03-22 13:40:48 March 82923
2022-04-01 00:14:33 April 23333
2022-05-01 00:31:58 May 33322
2022-06-06 17:21:29 June 33244
2022-07-01 04:19:20 July 90283
2022-08-01 00:07:04 August 8428
2022-09-01 09:40:15 September 10097
2022-10-01 00:30:19 October 6421
2021-12-01 07:12:30 December 8521
the query im using is below
SELECT
created_on as 'time',
MONTHNAME(created_on) AS 'month_name',
count(distinct id_number) AS "inc_number"
FROM test_reports
WHERE
MONTH(created_on)
GROUP BY MONTH(created_on)
ORDER BY MONTH(created_on)
Please suggest the way to get all time should be first date of each month.
If you use GROUP BY and do not specify a column, MySQL will just use one of the created_on values from the 'array'.
Instead you should define the expected output of created_on and add it to your GROUP BY
You could use something like DATE_FORMAT(created_on, '%Y-%m-01') to always display the first day of that month
working, thanks #verhie
SELECT
created_on as 'time',
MONTHNAME(created_on) AS 'month_name',
count(distinct id_number) AS "inc_number"
FROM test_reports
WHERE
MONTH(created_on)
GROUP BY DATE_FORMAT(created_on, '%Y-%m-01')
ORDER BY MONTH(created_on)

Get the count of rows for each month in specific date range

I have list of records in table A and want to get the count of records for each month in range of days, starting from first of this month to the current day. So if we have 3 months and the current day is 19, So for the first month i need count of records between 1st to 19th of the month, and for the second month from 1st to 19th and so on.
id time
1 2005-07-05 14:10:29
2 2005-07-12 15:47:35
3 2005-08-02 16:38:53
4 2005-08-04 10:48:12
5 2006-08-22 17:34:28
6 2006-09-01 22:11:35
7 2006-09-09 15:10:19
8 2006-09-06 21:55:56
The desired Result:
time count
2005-07 2
2005-08 2
2006-09 3
we ignored the record id 5 because we just count the days between 1st and 19th for each month.
How can i do this?
You cam filter the rows with the function DAY() and aggregate:
SELECT DATE_FORMAT(time, '%Y-%m') yearmonth,
COUNT(*) counter
FROM tablename
WHERE DAY(time) <= DAY(CURRENT_DATE)
GROUP BY yearmonth
See the demo.
Results:
yearmonth
counter
2005-07
2
2005-08
2
2006-09
3

group by date containing certain date only

I have tried looking at some similar examples like group by date range and weekdays etc but I couldnt fix it on my query.
as per my sample data screenshot, I need to only return
sum(salesamount)/sum(salescount) for week 1
and
sum(salesamount)/sum(salescount) for week 2.
Each of the week contain 5 days (in this example is wednesday - sunday).
My Attempt:
select salesstartdate, date_add(salesstartdate, interval 5 day) as gdate,
salesamount, salescount, sum(salesamount)/sum(salescount) as ATV
from testing
group by gdate;
My desired output is:
Week 1 15.34173913
Week 2 15.80365088
Calculation to get week 1 is (3507.1+3639.97+5258.77+8417.04+5994.48)/(285+273+344+478+368)
Calculation to get week 2 is the same as above except the date would now be from 8 to 12 of June.
You can do it with a subquery. In order to first group your result set properly and then execute aggregation on it:
SELECT
concat('WEEK', ' ', weekno) as `Week #`,
MIN(salesstartdate) as startDate,
MAX(salesstartdate) as endDate,
sum(salesamount)/sum(salescount) as ATV
FROM
(
SELECT
salesstartdate,
salesamount,
salescount,
WEEKOFYEAR(salesstartdate) as weekno -- get the week number of the current year
FROM
weekno
WHERE
WEEKDAY(salesstartdate) BETWEEN 2 AND 6 -- get index of week day
) as weeks
GROUP BY
weekno
I have used 2 MySQL functions here:
WEEKOFYEAR()
WEEKDAY()
Output:
WEEK 23 | 2016-06-08 | 2016-06-12 | 15.8040
WEEK 24 | 2016-06-16 | 2016-06-19 | 15.9323
and without subquery as well:
SELECT
concat('WEEK', ' ', WEEKOFYEAR(salesstartdate)) as `Week #`,
MIN(salesstartdate) as startDate,
MAX(salesstartdate) as endDate,
sum(salesamount)/sum(salescount) as ATV
FROM
weekno
WHERE
WEEKDAY(salesstartdate) BETWEEN 2 AND 6 -- get index of week day
GROUP BY
WEEKOFYEAR(salesstartdate)
You can do this way
select SUBDATE(salesstartdate, WEEKDAY(salesstartdate)) as week_range
, sum(salesamount)/sum(salescount)
from testing
where salesstartdate between SUBDATE(salesstartdate, WEEKDAY(salesstartdate))
and date_add(SUBDATE(salesstartdate, WEEKDAY(salesstartdate)), interval 5 day))
Group by week_range

Count all type devices by week

I have a table:
idint(11) NOT NULL
type varchar(64) NOT NULL
created_on datetime NOT NULL
Can I count all type devices (iSO, Android...) by week in one query when use doctrine2?
Sample output:
Week iOS Android Other
1 4 5 6
2 3 5 9
This is entirely possible, using methods similar to that detailed in Output Sum of some column in week intervals throughout a year, week dates consistent with day however not easily in the output you described. The best way to handle this will be to do a SELECT, grouping on WEEK and TYPE. I.e.
SELECT
-- Get the week and month of each row
YEAR(created_on) AS Year,
WEEK(created_on) AS Week,
type
-- Count how many rows are in this group
COUNT(*) AS frequency
FROM yourTable AS yt
-- Order by month and then week, so that week 4 in Jan comes before week 4 in Feb
GROUP BY
Year ASC,
Week ASC,
type ASC
This would give output such as
Year Week Type frequency
2013 1 'iOS' 4
2013 1 'Android' 5
2013 1 'Other' 6
2013 2 'iOS' 3
2013 2 'Android' 5
2013 2 'Other' 9