Count Distinct Date MySQL returning one row - mysql

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);

Related

Backfill data using coalesce

I am trying to backfill data using a coalesce function, alongside first_value and last_value functions, however the records do not seem to be populating.
In the example picture, I would like the cellphone number 033333333 to be populated from that row until the 0444444444 record row, and then to have the 0444444444 value persist until the end , or until if there were a new value eg.05555555555.
This is the code that I have tried running, however it has had no effect on the output.
,CASE WHEN Contact_RowNum = 1 AND dim_active = 0 AND Contact_CellPhoneNumber IS NULL THEN NULL
WHEN Contact_RowNum = 1 and dim_active in(0,1) THEN Contact_CellPhoneNumber
WHEN Contact_RowNum IS NULL OR Contact_RowNum !=1 THEN
coalesce
(
last_value(Contact_CellPhoneNumber) over (PARTITION BY InvolvedPartyId,dim_Active order by RecordValidityStartDate desc ),
first_value(Contact_CellPhoneNumber) over (PARTITION BY InvolvedPartyId,dim_Active order by RecordValidityStartDate desc
RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
)
)

Cyclical update in the same table - complementary

Respected all,
I have the following query that is executed only for a date by the filter that is noted, what I need is to run for all the dates in the table, and I can not find the way to indicate that function, I appreciate its special orientation:
update scraper_data_twitter as T1,
(
select Ntweets as Ntweets_var,
(
select COUNT(Ntweets) + 1
from scraper_data_twitter
where (NTweets > Ntweets_var)
and date = '2017-02-13'
) as rank
from scraper_data_twitter
where date = '2017-02-13'
group by SITE,
date
order by NTweets_var desc
) as A
set T1.rnk_Ntweets = A.rank
where T1.ntweets = A.Ntweets_var

MySQL: Undesired result with max function on a timestamp

I use a Mantis Bug Database (that uses MySQL) and I want to query which bugs had a change in their severity within the last 2 weeks, however only the last severity change of the bug should be indicated.
The problem is, that I get multiple entries per bugID (which is the primary key), which is not my desired result since I want to have only the latest change per bug. This means that somehow I am using the max function and the group by clause wrongfully.
Here you can see my query:
SELECT `bug_id`,
max(date_format(from_unixtime(`mantis_bug_history_table`.`date_modified`),'%Y-%m-%d %h:%i:%s')) AS `Severity_changed`,
`mantis_bug_history_table`.`old_value`,
`mantis_bug_history_table`.`new_value`
from `prepared_bug_list`
join `mantis_bug_history_table` on `prepared_bug_list`.`bug_id` = `mantis_bug_history_table`.`bug_id`
where (`mantis_bug_history_table`.`field_name` like 'severity')
group by `bug_id`,`old_value`,`.`new_value`
having (`Severity_modified` >= (now() - interval 2 week))
order by bug_id` ASC
For the bug with the id 8 for example I get three entries with this query. The bug with the id 8 had indeed three severity changes within the last 2 weeks but I only want to get the latest severity change.
What could be the problem with my query?
max() is an aggregation function and it does not appear to be suitable for what you are trying to do.
I have feeling that what you are trying to do is to get the latest out of all the applicable bug_id in mantis_bug_history_table . If that is true, then I would rewrite the query as the following -- I would write a sub-query getLatest and join it with prepared_bug_list
Updated answer
Caution: I don't have access to the actual DB tables so this query may have bugs
select
`getLatest`.`last_bug_id`
, `mantis_bug_history_table`.`date_modified`
, `mantis_bug_history_table`.`old_value`
, `mantis_bug_history_table`.`new_value`
from
(
select
(
select
`bug_id`
from
`mantis_bug_history_table`
where
`date_modified` > unix_timestamp() - 14*24*3600 -- two weeks
and `field_name` like 'severity'
and `bug_id` = `prepared_bug_list`.`bug_id`
order by
`date_modified` desc
limit 1
) as `last_bug_id`
from
`prepared_bug_list`
) as `getLatest`
inner join `mantis_bug_history_table`
on `prepared_bug_list`.`bug_id` = `getLatest`.`last_bug_id`
order by `getLatest`.`bug_id` ASC
I finally have a solution! I friend of mine helped me and one part of the solution was to include the Primary key of the mantis bug history table, which is not the bug_id, but the column id, which is a consecutive number.
Another part of the solution was the subquery in the where clause:
select `prepared_bug_list`.`bug_id` AS `bug_id`,
`mantis_bug_history_table`.`old_value` AS `old_value`,
`mantis_bug_history_table`.`new_value` AS `new_value`,
`mantis_bug_history_table`.`type` AS `type`,
date_format(from_unixtime(`mantis_bug_history_table`.`date_modified`),'%Y-%m-%d %H:%i:%s') AS `date_modified`
FROM `prepared_bug_list`
JOIN mantis_import.mantis_bug_history_table
ON `prepared_bug_list`.`bug_id` = mantis_bug_history_table.bug_id
where (mantis_bug_history_table.id = -- id = that is the id of every history entry, not confuse with bug_id
(select `mantis_bug_history_table`.`id` from `mantis_bug_history_table`
where ((`mantis_bug_history_table`.`field_name` = 'severity')
and (`mantis_bug_history_table`.`bug_id` = `prepared_bug_list`.`bug_id`))
order by `mantis_bug_history_table`.`date_modified` desc limit 1)
and `date_modified` > unix_timestamp() - 14*24*3600 )
order by `prepared_bug_list`.`bug_id`,`mantis_bug_history_table`.`date_modified` desc

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 :)

SQL request for report

There is a problem with the writing of the request for the report, which reflects the number of events is created and updated every day.
The table includes:
FieldTypeComment
id int (11) NOT NULL
name varchar (255) NULL
created_on datetime NOT NULL
updated_on datetime NOT NULL
Created and updated date may not coincide.
request:
SELECT
z.date_created,
SUM (IF (z.date_created = z.date_updated, 1, 0)) AS created,
SUM (IF (z.date_created! = Z.date_updated, 1, 0)) AS updated
FROM
(
SELECT
SUBSTRING (e.updated_on, 1, 10) AS date_updated,
SUBSTRING (e.created_on, 1, 10) AS date_created
FROM
event e
) z
GROUP BY
z.date_created
I need the following result:
Does not give the desired result, because does not show all dates.
Assuming you want
see all dates;
count create in fact;
count update only if it is other date than create:
http://www.sqlfiddle.com/#!2/56254/39
SELECT A.*
,(SELECT count(created_on)
FROM event WHERE date=created_on) created
,(SELECT sum(created_on<>updated_on)
FROM event WHERE date=updated_on) updated
FROM (
SELECT created_on date FROM event
UNION SELECT updated_on FROM event ) A
To get number of events created and updated on a particular day, do something like this.
select count(*) events
from event
where
(created_on >= {d '2013-02-10'} and created_on < {d '2013-02-11'})
or
(updated_on >= {d '2013-02-10'} and updated_on < {d '2013-02-11'})
This approach takes the time portion of those fields into account.