MySQL multiple if statements for dates - mysql

I'm trying to get the date difference between two columns and then ultimately, get the average days grouped by the contractor field. I was able to get most of the SQL down but I can't seem to figure out how to get the date difference for multiple if scenarios.
Basically, if the original date column is null and the new date column is not, get the date difference between the new date and date ordered. Vice versa. If both original and new date are null, just set the date diff to null. It should look like below, without accounting for the grouped average days.
SQL below (didn't include avg function yet):
SELECT PT1.CONTRACTOR AS 'Contractor', PT1.date_order AS "date ordered", PT1.DATE_COMPLETED AS "original date", PT2.DATE_COMPLETED AS "new date",
IF(PT1.DATE_COMPLETED = NULL AND PT2.DATE_COMPLETED IS NOT NULL, DATEDIFF(PT2.DATE_COMPLETED, PT1.DATE_ORDER), IF(PT2.DATE_COMPLETED = NULL AND PT1.DATE_COMPLETED IS NOT NULL, DATEDIFF(PT1.DATE_COMPLETED, PT1.DATE_ORDER), NULL)) AS "DATE DIFF"
FROM PTABLE1 PT1
INNER JOIN PTABLE2 PT2
ON PT1.ID = PT2.ID
WHERE PT2.STATUS = 'To_do' OR PT2.STATUS = 'Completed'
AND PT2.COMPLETE = 'Yes'
-- GROUP BY PT1.CONTRACTOR

COALESCE is your friend - it returns the first non-null value in a list, or NULL if they are all NULL.
So what you want is probably
datediff(coalesce(original_date, new_date), order_date)
If both are null, datediff will return null.

Related

How to compare a date with array of dates in SQL query and update a field value in MySQL?

I'm working on a task where I need to find the expected date to resolve a ticket using createdAt and sla_name fields values. After that I need to compare the this expected date with the dates in holidays table.
If the expected date falls in holidays, I need to extend the sla_name field value.
This is the query am using.
SELECT t.sla_meet, t.tid, t.ticket_id, t.ticket_name,t.createdAt,t.updatedAt,t.status, dw.dropdown_name
as ticket_priority,p.project_name, dw3.dropdown_name as ticket_status,t.sla as sla_name,
isn.issue_name as issue_type,inn.incidentName as incident_type,t.ticket_accepted_date,
t.asset_id,t.ticket_closed_date,t.contact_number,
IF(NOW() <= DATE_ADD(t.createdAt,INTERVAL (t.sla)+1 DAY),'YES','NO') AS slaMeetData
from tickets t
JOIN assets ast ON t.asset_id=ast.asset_id
JOIN projects p ON p.project_id=ast.project_id
JOIN admin_dropdowns dw ON t.ticket_priority=dw.id
JOIN admin_dropdowns dw3 ON t.ticket_status=dw3.id
JOIN issues isn ON t.issue_type=isn.issue_id
JOIN incident_names inn ON t.incident_type=inn.incidentId
order by t.tid DESC
This is the resultant data of the above query.
Now I need to compare the holidays in above query. And the sample data is,
If the expected date that am getting in IF condition of above query is falls in this holidays, I need to update the sla_name value with COUNT OF HOLIDAYS(If startdata and enddate are there, need to count the days between them) + sla_name.
If expected date is falls on dates range(start and end dates of holidays), need to calculate the count of days from expected date to end date and update that count in sla_name field
Is it possible to do this functionality in SQL? I've used the above query as VIEWS.
Instead of t.sla AS sla_name, use this expression to determine whether to add the length of the overlapping holiday to the number of days:
(
t.sla +
IF(
DATE_ADD(t.createdAt,INTERVAL (t.sla)+1 DAY) BETWEEN holidays.holiday_date AND holidays.end_date,
DATEDIFF( holidays.end_date, holidays.holiday_date ), /* add holiday length number of days */
0 /* no holiday overlap so don't add any days */
)
) as sla_name
You'll also have to join on the holidays table to find the holiday (if any) which overlaps the date in question:
JOIN holidays ON ( DATE_ADD(t.createdAt,INTERVAL (t.sla)+1 DAY) BETWEEN holidays.holiday_date and holidays.end_date )

Count Distinct Date MySQL returning one row

Ok so be ready I'm working on a weird base :
Every table has 3 column only : varchar('Object'),varchar('Property'),varchar('Value')
Here is a fiddle I've build with examples of my tries
http://sqlfiddle.com/#!9/de22eb/1
I need to extract the last time a server was update. But i'm not interested in the server itself it's more about the date. Once I know that there was an update for a date I'm looking to count every updates on that day.
To do so I'm using 2 tables : the server table
CREATE TABLE IF NOT EXISTS `server` (
`name` varchar(80) NOT NULL,
`field` varchar(80) NOT NULL,
`value` varchar(200) NOT NULL
);
And the event table :
CREATE TABLE IF NOT EXISTS `event` (
`name` varchar(80) NOT NULL,
`field` varchar(80) NOT NULL,
`value` varchar(80) NOT NULL
);
Please go watch the fiddle to have an idea of the content.
I want to have a result like this (based on my example) :
Date Number patched
2017-11-14 2
2017-11-04 1
The problem is that I don't know where I'm wrong on my query (I've separated the step for better understanding inside the fiddle) :
Select date_format(d.val, '%Y-%m-%d') as 'Date', COUNT(distinct
date_format(d.val, '%Y-%m-%d')) as 'Number'
FROM (
Select b.serv,b.val
FROM (
Select serv,val FROM (
Select name as serv, value as val FROM event
where field='server_vers' and
value!='None'
order by serv ASC,
val DESC LIMIT 18446744073709551615) a
group by a.serv) b,
server c
where b.serv = c.name and c.field = 'OS' and c.value = 'Fedora'
) d group by date_format(d.val, '%Y-%m-%d');
It's giving me only one row. Adding group by date_format(d.val, '%Y-%m-%d') at the end makes the Count useless. How can I fix that ?
I want to have for each server for a given OS type the last patch date and then sum the result by date.
Is that what you needed ?
SELECT dates.date, COUNT(dates.date) as patch_count
FROM (
SELECT MAX(date_format(event.value, '%Y-%m-%d')) as date
FROM event
JOIN server ON (event.name = server.name)
WHERE (server.field = 'OS' AND server.value = 'Fedora')
GROUP BY event.name ) as dates
GROUP BY 1
ORDER BY 2 DESC
Here's the fiddle :
http://sqlfiddle.com/#!9/de22eb/37/0
Explanation : We get the last date for every server name. That gives a list of last dates. Then we use this as a table, that we can group on to count each different value.
The datetimes are stored as strings. The first ten characters of that string represent the date. So you get the date with left(value, 10).
You get the last update per server by grouping by server and retrieving max(left(value, 10)), because alphabetic order works on 'yyyy-mm-dd'.
select name, max(left(value, 10))
from event
where field = 'server_vers'
and value <> 'None'
group by name
Build up on this to get the count of updates on those last-update dates:
select left(value, 10), count(*)
from event
where field = 'server_vers'
and left(value, 10) in
(
select max(left(value, 10))
from event
where field = 'server_vers'
and value <> 'None'
group by name
)
group by left(value, 10)
order by left(value, 10);

MySQL select records using MAX(datefield) minus three days

Clearly, I am missing the forest for the trees...I am missing something obvious here!
Scenario:
I've a typical table asset_locator with multiple fields:
id, int(11) PRIMARY
logref, int(11)
unitno, int(11)
tunits, int(11)
operator, varchar(24)
lineid, varchar(24)
uniqueid, varchar(64)
timestamp, timestamp
My current challenge is to SELECT records from this table based on a date range. More specifically, a date range using the MAX(timestamp) field.
So...when selecting I need to start with the latest timestamp value and go back 3 days.
EX: I select all records WHERE the lineid = 'xyz' and going back 3 days from the latest timestamp. Below is an actual example (of the dozens) I've been trying to run.
MySQL returns a single row with all NULL values for the following:
SELECT id, logref, unitno, tunits, operator, lineid,
uniqueid, timestamp, MAX( timestamp ) AS maxdate
FROM asset_locator
WHERE 'maxdate' < DATE_ADD('maxdate',INTERVAL -3 DAY)
ORDER BY uniqueid DESC
There MUST be something obvious I am missing. If anyone has any ideas, please share.
Many thanks!
MAX() is an aggregated function, which means your SELECT will always return one row containing the maximum value. Unless you use GROUP BY, but it looks that's not what you need.
http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_max
If you need all the entries between MAX(timestamp) and 3 days before, then you need to do a subselect to obtain the max date, and after that use it in the search condition. Like this:
SELECT id, logref, unitno, tunits, operator, lineid, uniqueid, timestamp
FROM asset_locator
WHERE timestamp >= DATE_ADD( (SELECT MAX(timestamp) FROM asset_locator), INTERVAL -3 DAY)
It will still run efficiently as long as you have an index defined on timestamp column.
Note: In your example
WHERE 'maxdate' < DATE_ADD('maxdate',INTERVAL -3 DAY)
Here you were are actually using the string "maxdate" because of the quotes causing the condition to return false. That's why you were seeing NULL for all fields.
Edit: Oops, forgot the "FROM asset_locator" in query. It got lost at some point when writing the answer :)

How to compare dates in sql query?

I am writing a function that brings me all the matches of specific month and year.
I pass the month number and the year value to that function and it should use the following query to get the results:
SELECT tahminler.match_id, tahminler.tahmin_text,matches_of_comments.match_id
FROM tahminler
INNER JOIN matches_of_comments ON tahminler.match_id = matches_of_comments.match_id
WHERE (
matches_of_comments.match_date = 'I DO NOT KNOW WHAT TO WRITE HERE'
)
AND tahminler.user_id =12
The problem is the matches_of_comments.match_date type is varchar and i pass values of the month and year as numbers to make a form like 11.2013 how can i compare this form that i pass to the varchar date ?? can i convert the type into date ?? and if i can do that how to compare part of the date (just month and year)??
Try this one convert to date first then compare month and year ,note it is bad practiceto store date as varchar
SELECT tahminler.match_id, tahminler.tahmin_text,matches_of_comments.match_id
FROM tahminler
INNER JOIN matches_of_comments ON tahminler.match_id = matches_of_comments.match_id
WHERE (
MONTH(STR_TO_DATE(matches_of_comments.match_date , '%m/%d/%Y'))= '07'//month variable
AND YEAR(STR_TO_DATE(matches_of_comments.match_date , '%m/%d/%Y'))= '2013'//year variable
)
AND tahminler.user_id =12
STR_TO_DATE(str,format)
MONTH
YEAR
STR_TO_DATE('11.2013', '%m.%Y')
will convert the string into a datetime datatype.
To compare in any format you need you can reformat it:
DATE_FORMAT(STR_TO_DATE('11.2013', '%m.%Y'), '%Y-%m-%d')

How to retrieve data from database table with condition in between date?

I need to check the available hotels and quantity of rooms available on the hotels for some duration(start_date and end_date.
I have a table test(id, date, qty, hotel_id). I need to access all the the hotel ids with some condition on qty (eg. qty>2) and date between two dates(for eg: the date field of the test table should have date value greater than the '2013-05-06' and end date less than '2013-05-10').
I tried this query:
select hotel_id
from test
where qty>2
and date between '2013-05-06' and '2013-05-10';
But, another condition is there must be all date between given dates. i.e. the date field should have all date date values: '2013-05-06', '2013-05-07', '2013-05-08', '2013-05-09', '2013-05-10' . If any of the above date is missing, then it should return empty resultset. And if all date are available with qty>2(let), then it should return list of hotel_ids.
How can it be done in a single MySQL query?
Try
SELECT `hotel_id`
FROM test
WHERE `date` BETWEEN '2013-05-06' AND '2013-05-10'
AND `qty` >= 2
GROUP BY `hotel_id`
HAVING COUNT(*) = (DATEDIFF('2013-05-10', '2013-05-06') + 1)
SQLFiddle