Using DATEDIFF to ignore negative values in MYSQL - mysql

I have a requirement where I need to check the sent date of various email threads against date column in another table and determine version number if email sent date occurs after the date specified in the table. I used datediff() for this but I get negative values. I can't use ABS() because it doesn't make sense here.Is there any way I can get the desired result? A sample of the query I am using is
select distinct
x.OPTENTION_DATE,
email.ID,
x.NAME,
email.SEND_DATE,
DATEDIFF(email.SEND_DATE, x.OPTENTION_DATE) AS DT_DIFF
from
classification_version x,
classification_element y,
email
where
x.id_project = y.ID_PROJECT and
x.ID_PROJECT = email.ID_PROJECT_AMENDMENT and
y.ID_PROJECT = 11 and
y.ID_COMPANY=1
order by
email.SEND_DATE ASC
The output for this query is
OPTENTION_DATE ID NAME SEND_DATE DT_DIFF
2014-11-05 3 Version 2 2014-01-13 14:09:34 -296
2015-02-18 3 Version 3 2014-01-13 14:09:34 -401
2014-01-09 3 Version 1 2014-01-13 14:09:34 4
2014-11-05 62 Version 2 2015-01-12 18:46:10 68
2015-02-18 62 Version 3 2015-01-12 18:46:10 -37
2014-01-09 62 Version 1 2015-01-12 18:46:10 368
2014-11-05 61 Version 2 2015-01-19 20:50:09 75
2015-02-18 61 Version 3 2015-01-19 20:50:09 -30
2014-01-09 61 Version 1 2015-01-19 20:50:09 375
My desired output is for email id 3 version 1 should be selected,for email id 62 version 2 should be selected. If I use ABS() and then MIN() version 3 will be selected which is wrong because the send date is before the actual date.Can anyone suggest how to solve this?

You can use email.SEND_DATE > x.OPTENTION_DATE condition in WHERE clause and use MIN(DATEDIFF(email.SEND_DATE, x.OPTENTION_DATE)) and GROUP BY ID. It will find minimum positive value for each id.
Try below query :
select x.OPTENTION_DATE,
email.ID,
x.NAME,
email.SEND_DATE,
MIN(DATEDIFF(email.SEND_DATE, x.OPTENTION_DATE)) AS DT_DIFF
from
classification_version x,
classification_element y,
email
where
x.id_project = y.ID_PROJECT
and x.ID_PROJECT = email.ID_PROJECT_AMENDMENT
and y.ID_PROJECT = 11
and y.ID_COMPANY=1
and email.SEND_DATE > x.OPTENTION_DATE
group by
ID
order by
email.SEND_DATE ASC

Related

MySQL: Get count for each range

There is mysql Ver 8.0.18 value_table as:
value count
1 3
11 1
12 2
22 5
31 1
34 3
35 1
40 3
46 7
What is query to get a total count for each dozen (1-10 - first dozen,11-20 - second , etc..)
as:
1 3
2 3
3 5
4 8
5 7
Query should be flexible, so when some records added to value_table , for example
51 2
62 3
so, it is not necessary to change a query by adding new range (51-60 - 6-th dozen, etc.)
I think you just want division and aggregation:
select min(value), sum(count)
from t
group by floor(value / 10);
To be honest, I'm not sure if the first column should be min(value) or floor(value / 10) + 1.

last entered value row in group by Mysql

My Query-
SELECT id, MAX(sl), details_sp FROM shareholderreceive GROUP BY id
and result
id MAX(sl) details_sp
1 76
2 74
3 64
4 67
5 69
6 70
10 72
But i need Those MAX(sl) Where details_sp column has last entered value.
My expected table is -
id MAX(sl) details_sp
1 72 Jul'16
2 74
3 64
4 62 Aug'16
5 69
6 70
10 71 Aug'16
here, data type details_sp is Varchar.
What query do I need to get this in MySQL?
What I think you mean is that when there is a details_sp filled in you need the sl value of that row and when there is no details_sp you need the max sl value?
If so, don't use MAX() but use the ORDER BY with the GROUP BY.
SELECT id, sl, details_sp
FROM shareholderreceive
ORDER BY details_sp DESC, sl DESC
GROUP BY id
The only problem with this is that you can never order by a date when it is a varchar value. This means you can never get the latest entry with just a varchar as a date.
So if there is a way, make the details_sp a date value (when you don't have a day just use the first day of the month, so 2017-06-01 for juli 2017) and use DATE_FORMAT() in MySQL or date_format in PHP (or JAVA or etc).

compare max value within a range with a specific date using group by

I want mysql query to check if the end date's high value is greater than all high within one year range from end date -1 day for that symbol.
MAX with group by and checking it with correct symbol for comparison. How do I go on with this?
My table structure is:
id Symbol date high
1 ABC 2015-01-23 45
2 ABC 2015-01-22 40
3 ABC 2014-01-28 33
4 xyz 2015-01-23 37
5 xyz 2015-01-20 70
6 ANO 2015-01-20 170
7 JE 2015-01-25 560
8 JE 2015-01-23 770
SELECT `symbol`,`high` as current_high from history as h
where date='2015-01-23'
AND symbol = 'ABC';
SELECT `date`,`symbol`, MAX(`high`) as 1_yrhigh from history
where date between '2014-01-23'
and '2015-01-22' AND symbol='ABC'
want results if current_high > 1yr_high
So from above sample table's query result should be
1 ABC 2015-01-23 45
8 JE 2015-01-23 770
xyz is not displayed as 37 < max ie 70
ANO is not displayed as no record for 2015-01-23 is present
In Order to get current high for each symbol use below query
Select symbol,MAX(high) as currentHigh
From table
Where date=CURDATE()
Group By symbol
In Order to get last 1 year high except current date use below query
Select symbol,MAX(high) as lastOneYrHigh
From table
Where date between (CURDATE()-INTERVAL 1 DAY-INTERVAL 1 YEAR)-(CURDATE() - INTERVAL 1 DAY)
Group By symbol

Does any way to get the last inserted values in each days

id date calls
5 2015-02-17 01:06:01 1
6 2015-02-17 11:07:01 2
7 2015-02-17 23:06:01 3
8 2015-02-18 03:07:01 1
9 2015-02-18 09:06:01 2
10 2015-02-18 17:07:01 3
11 2015-02-18 22:06:01 4
12 2015-02-19 01:07:01 1
13 2015-02-19 08:06:01 2
14 2015-02-19 18:07:01 3
15 2015-02-19 23:06:01 4
my table structure is like this and I need to calculate the sum of call in each days. In this table, you can see that, the last call in feb 17 was at 23:06:01 and call count was 3. In feb 18 was at 22:06:01 and call count was 4. Can I get the sum of all this last call counts of each day.
You can use a subquery to determine which rows to sum (the ones matching the last call for each date, using MySQL it would be:
select sum(calls) sum_last_calls
from your_table
where `date` in (
select max(date) max_date
from your_table
group by date(`date`)
)
This query will return 11 as the sum (from 3+4+4).
The date() function used in the subquery is specific to your database and might need to be changed according to your specific database syntax - the point is that it should return the date without time (it could be date::date (Postgresql) or cast(date as date) (MSSQL and others)).
Sample SQL Fiddle for MySQL and Postgresql
Postgresql version:
select sum(calls) as calls
from (
select max(calls) as calls
from t
where date::date between '2015-02-17' and '2015-02-19'
group by date::date
) s

Cannot print out the latest results of table

I have the following table:
NAMES:
Fname | stime | etime | Ver | Rslt
x 4 5 1.01 Pass
x 8 10 1.01 Fail
x 6 7 1.02 Pass
y 4 8 1.01 Fail
y 9 10 1.01 Fail
y 11 12 1.01 Pass
y 10 14 1.02 Fail
m 1 2 1.01 Fail
m 4 6 1.01 Fail
The result I am trying to output is:
x 8 10 1.01 Fail
x 6 7 1.02 Pass
y 11 12 1.01 Pass
y 10 14 1.02 Fail
m 4 6 1.01 Fail
What the result means:
Fnames are an example of tests that are run. Each test was run on different platforms of software (The version numbers) Some tests were run on the same platform twice: It passed the first time and failed the second time or vice versa. My required output is basically the latest result of each case for each version. So basically the results above are all unique by their combination of Fname and Ver(sion), and they are selected by the latest etime from the unique group.
The query I have so far is:
select Fname,stime,max(etime),ver,Rslt from NAMES group by Fname,Rslt;
This however, does not give me the required output.
The output I get is (wrong):
x 4 10 1.01 Fail
x 6 7 1.02 Pass
y 4 12 1.01 Pass
y 10 14 1.02 Fail
m 1 6 1.01 Fail
Basically it takes the max time, but it does not really print the correct data out, it prints the max time, but it prints the initial time of the whole unique group of data, instead of the initial time of that particular test (record).
I have tried so long to fix this, but I seem to be going no where. I have a feeling there is a join somewhere in here, but I tried that too, no luck.
Any help is appreciated,
Thank you.
Use a subquery to get the max ETime by FName and Ver, then join your main table to it:
SELECT
NAMES.FName,
NAMES.STime,
NAMES.ETime,
NAMES.Ver,
NAMES.Rslt
FROM NAMES
INNER JOIN (
SELECT FName, Ver, MAX(ETime) AS MaxETime
FROM NAMES
GROUP BY FName, Ver
) T ON NAMES.FName = T.FName AND NAMES.Ver = T.Ver AND NAMES.ETime = T.MaxETime
You could first find which is the latests=max(etime) for each case for each version ?
select Fname,Ver,max(etime) from NAMES group by Fname,Ver;
From there you would display the whole thing via joining it again?
select *
from
NAMES
inner join
(select Fname,Ver,max(etime) as etime from NAMES group by Fname,Ver ) sub1
using (Fname,Ver,etime)
order by fname,Ver;