group by based on part of a column value in mySql - mysql

I have a mySql table call details. details table is having a column call date which is having date like 2015-02-01. There can be multiple rows from a same date.
I want to find how many rows COUNT() it contains for each month of the year.
for example,
'568', '192.168.1.100', '790', '1.00', '2014-11-14'
'569', '192.168.1.100', '780', '1.00', '2014-11-14'
'699', '192.168.1.100', '780', '1.00', '2014-11-16'
'767', '192.168.1.102', '780', '1.00', '2014-12-15'
'768', '192.168.1.102', '780', '1.00', '2014-12-15'
this should give COUNT like:
'2014-11-' as 3
'2014-12-' as 2
How can i do it using a sql select query.

Select DATE_FORMAT(My_Call_Date_Field, '%Y-%m') as MyYearAndMonth, Count(*) as MyCount
From My_Call_Details_Table Group By DATE_FORMAT(My_Call_Date_Field, '%Y-%m')
You can also use the CAST function of MySql.
Select substr(convert(My_Call_Date_Field, CHAR), 1, 7) as MyYearAndMonth, Count(*) From My_Call_Details_Table Group By substr(convert(My_Call_Date_Field, CHAR), 1, 7) Order By substr(convert(My_Call_Date_Field, CHAR), 1, 7)
In response to additional info specific to your case, as seen in your comment to the previous answer by Ed King: here it is :
SELECT DATE_FORMAT(detailtable.date, '%Y-%m') , AVG(detailtable.loadstate) as "load",count(detailtable.loadstate) as "count" from ruby_snmp.detailtable where ipaddtress='192.168.1.102' and date LIKE '2014-12-%' GROUP BY DATE_FORMAT(detailtable.date, '%Y-%m')

Convert to month and year using mysql functions, group and count:
SELECT month(calldate) as m, year(calldate) as y, count(*)
FROM calldetails
GROUP by m, y;
Given the additional information, I would do the following:
SELECT YEAR(detailtable.date) as y,
MONTH(detailtable.date) as m,
AVG(detailtable.loadstate) as "load",
count(detailtable.loadstate) as "count"
FROM ruby_snmp.detailtable
WHERE ipaddtress='192.168.1.102' and date LIKE '2014-12-%'
GROUP BY y, m;
The format variables y and m would be disregarded, but need to be there for the group to work. You can add the FORMAT function to give the specific YYYY-MM as was mentioned in the second post, or you can handle data presentation in the program / report writer.

Related

Query for fetching the count of records each month

I am trying to fetch the count of records entered in each month of the financial year
For example, I have declared a column called issue in varchar because the data what I am taking is issues of the particular machine. And for example, let's say one issue is raised in July month I enter the data as 'Jul 19-1' and the again issue is raised in the month of September again I go back to the issue happened in July and enter the data as 'sep19-2'.
So in the backend, it takes as jul19-1 sep19-2
What can be the query that I can write for counting the number of issues raised in each month
I tried the below query but
SELECT COUNT(month_nc)
FROM `ncr`
WHERE month_nc='Jul18-1'
In some months there will be only one issue so I can the count of the month given in the above query
What will be the query if I want to fetch the count of each month
id issue issue_month
1 bearing jul18-1
sep18-2
2 motor jul18-2
3 battery apr18-3
ps: issue_month is declared in varchar(10)
Here are two methods. One using strings:
select left(issue_month, 5), count(*)
from t
group by left(issue_month, 5), count(*)
This will not order the values correctly.
You can convert to a date to order properly:
order by str_to_date(concat('01', left(issue_month, 5)), '%d%b%y')
Or, represent the dates correctly:
select str_to_date(concat('01', left(issue_month, 5)), '%d%b%y') as yyyymm, count(*)
from t
group by yyyymm
order by yyyymm;
Here is what you can do to split your issue_month into "month_year" and "issue_count"
yourTable
select id,
issue,
issue_month,
REGEXP_SUBSTR(issue_month, '[^-]+', 1) as month_year,
REGEXP_SUBSTR(issue_month, '[^-]+', 1,2 ) as issue_count
from yourTable;
Now you can aggregate the issue_count across issues or year_months or any other field in your table.
For example, to get the sum of all the issues for any given month_year
select
month_year,
sum(issue_count) issue_count
from
(select
id, issue, issue_month,
REGEXP_SUBSTR(issue_month, '[^-]+', 1) as month_year,
REGEXP_SUBSTR(issue_month, '[^-]+', 1,2 ) as issue_count
from yourTable) foo
group by month_year;

Select data range when time and date are concatenated

I am currently using the line below to get the date
WHERE DATE (DateTime) BETWEEN '2016-12-19' AND '2016-12-23'
12/12/2016 09:31 - this is the date and time format
But it keeps on returning everything in the table from 2014.
The statement above seems to only work when its a short query but when I add a few lines to the SQL query it doesn't seem to work, Its extracting all dates in the table.
SELECT phone_number,system_outcome,DateTime
FROM calls
WHERE DATE (DateTime) BETWEEN '2016-12-19' AND '2016-12-23'
AND system_outcome = 'ANSWER_MACHINE'
GROUP BY phone_number
HAVING count(Phone_number) > 6
You need to learn to store dates in the correct format, not as a string. You can fix your where clause using date_format():
where date_format(left(date, 10), '%m/%d/%Y') between '2016-12-19' AND '2016-12-23'
I should also note that if you want phone numbers, then all other attributes should be the arguments of an aggregation function. Say:
SELECT phone_number, system_outcome, group_concat(DateTime)
FROM calls
WHERE date_format(left(date, 10), '%m/%d/%Y') BETWEEN '2016-12-19' AND '2016-12-23' AND
system_outcome = 'ANSWER_MACHINE'
GROUP BY phone_number, system_outcome
HAVING count(Phone_number) > 6;

Sorting Dates and serial number

Date SrNo
SEL/2016APR01/002/000001 01
SEL/2016APR02/002/000001 04
SEL/2016APR03/002/000001 03
SEL/2016JAN01/002/000001 02
I need to sort the first column Date part(2016JAN01) in Descending order and if there are two same dates then I need to sort the second column in Descending order.
substr('SEL/2016APR01/002/000001', 4,12) gives me 2016APR01 but I dont know how to sort dates of that format.
My query looks something like this
SELECT *
FROM tablename
ORDER BY substr(Date) DES, SrNo DESC
Update:
This first answer covers SQL Server, while the answer belows it is for MySQL. You originally tagged your question MySQL, and so everyone answered for that.
For SQL Server you can use CONVERT:
ORDER BY CONVERT(DATETIME,
SUBSTRING(Date, 12, 2) + ' ' +
SUBSTRING(Date, 9, 3) + ' ' +
SUBSTRING(Date, 5, 4),
106) DESC,
SrNo DESC
If you were actually using MySQL, then STR_TO_DATE would be the way to go:
ORDER BY STR_TO_DATE(SUBSTR(Date, 4, 12), '%Y%b%d') DESC,
SrNo DESC
Here is what the formatting parameters mean:
%Y - four digit year
%b - three letter month (e.g. JAN, APR)
%d - two digit day of month
If the upper case format of the month names results in STR_TO_DATE not working, you can try the following (which is admittedly a bit ugly):
ORDER BY STR_TO_DATE(
CONCAT(SUBSTRING(Date, 5, 4),
SUBSTRING(Date, 9, 1),
LOWER(SUBSTRING(Date, 10, 2)),
SUBSTRING(Date, 12, 2)),
'%Y%b%d') DESC,
SrNo DESC
As #RiggsFolly mentioned, your life would made easier if you stored your dates in a standard MySQL format.
Have you tried ORDER BY DATE_FORMAT(substr(Date, 4,12)), '%Y%b%d') DESC, SrNo DESC
use STR_TO_DATE FUNCTION
SELECT *
FROM tablename
ORDER BY STR_TO_DATE(SUBSTR(Date, 4, 12), '%Y%b%d') , SrNo DESC

Formatting SQL result as a sum

Here is the query I'm using to gather daily values from three different "addresses", which reference different sensors in our system.
SELECT DISTINCT
LEFT(changes.date_time, 6) AS 'date',
changes.address AS 'address',
(CASE WHEN changes.address IN (18) THEN - MAX(changes.value * types.multiplier) ELSE MAX(changes.value * types.multiplier) END) AS 'value'
FROM sensor.changes
INNER JOIN sensor.types ON changes.type = types.idx
WHERE
changes.address IN (1, 4, 8)
AND changes.date_time >= '12110100000000'
AND changes.date_time <= '13050100000000'
GROUP BY LEFT(changes.date_time, 6),
changes.address
ORDER BY changes.idx;
The first date contains the following values, with subsequent dates carrying the same addresses:
date address value
130203 1 0.0160
130203 4 0.1220
130203 8 -0.0070
I want to combine these three values, address 1+4+8, into a single row for that date. I've attempted a SUM on the "value" column, but that results in an SQL error: #1111 - Invalid use of group function. Taking out the second GROUP BY column results in one value per date, but the value is not a sum of those values. Using a second query to format the result is OK, but I would prefer if the math was done in the first query because the database server is not local.
EDIT: to clarify what I need as the result:
date address value
130203 1 0.131
The integer under the address column in this case doesn't matter.
You should add a grouping clause.
SELECT Resdate,SUM(Res.address),SUM(Res.value)
FROM
(
SELECT DISTINCT
LEFT(changes.date_time, 6) AS 'date',
changes.address AS 'address',
(CASE WHEN changes.address IN (18) THEN - MAX(changes.value * types.multiplier) ELSE MAX(changes.value * types.multiplier) END) AS 'value'
FROM sensor.changes
INNER JOIN sensor.types ON changes.type = types.idx
WHERE
changes.address IN (1, 4, 8)
AND changes.date_time >= '12110100000000'
AND changes.date_time <= '13050100000000'
GROUP BY LEFT(changes.date_time, 6),
changes.address
ORDER BY changes.idx
) AS Res
GROUP BY Res.Date

how to join 2 separate text to one - selected from string - IN MySQL

I have date in string like "01.02.2012" like "DD.MM.YYYY" and I need it convert to DATE or string like "YYYY-MM-DD".
I try:
SELECT SUBSTRING( txtdate, 7, 4 ) AS `year` , SUBSTRING( txtdate, 4, 2 ) AS `month` ,
SUBSTRING(txtdate, 1, 2 ) AS `day`
FROM info
So I get the year, month and day and now I want to join the texts to one.
I try this just after
SELECT CONCAT_WS('-',year,month,day);
but I get an error ..
You can't refer to aliased fields elsewhere in a field definition list, unfortunately.
SELECT x AS a, CONCAT(y, a)
doesn't work. You'd have to use
SELECT CONCAT_WS('-', SUBSTRING(txtdate, 7, 4), SUBSTRING(...), SUBSTRING(...))
or, if you'd stored that date in a proper DATE field in the database, it'd a simple matter of
SELECT DATE_FORMAT('%Y-%m-%d', datefield)