Zabbix DB: how events linked to hosts - zabbix

I want to create the custom report on event by 2 monitoring system.
I know about Zabbix API, but think
if I request data through the API, then the performance will not be the same if I perform queries directly to the database Zabbix.
I found a table with information about events,
SELECT eventid, source, object, objectid, clock, value, acknowledged, ns
FROM zabbix.events
Found zabbix.hosts and zabbix.host_inventory.
How is zabbix.events linked to zabbix.hosts?

You can check this link on the Zabbix share :
https://share.zabbix.com/databases/mysql/zabbix-database-model
Alain updates it pretty fast for every new release, and if you want to do some SQL queries, this is a must have.

objectid for trigger events (source=0) is the trigger ID, which in turn has function IDs, which in turn have item IDs, which in turn have host IDs.

The database schema is not documented officially, but you may find some community resources for that - http://zabbix.org/wiki/Database_Schemas. Just keep in mind that's 2.4.3 version. That is likely to be enough to find relations for your case.

information did compilate in this select:
SELECT * FROM events
JOIN triggers ON events.objectid = triggers.triggerid
JOIN functions ON functions.triggerid = triggers.triggerid
JOIN items ON items.itemid = functions.itemid
JOIN hosts ON items.hostid = hosts.hostid
WHERE events.source = 0
AND
LOWER(hosts.host) like 'mysql%'
AND events.clock>=unix_timestamp('2017-09-25 09:55:00')
AND events.clock<=unix_timestamp('2017-09-25 11:00:00')
ORDER BY events.clock DESC
;

This is a query I created to run against the zabbix db. It joins hosts and hostgroups, and then left joins acknowledged or unacknowledged events. once an event is resolved, it will drop off this query. It pulls for enabled or unreachable hosts.
select
h.name as hostname,
h.status as hoststatus,
g.name as groupname,
hi.alias as hostalias,
hi.location as hostlocation,
hi.os as hostos,
dt.idescription as itemdescription,
dt.ikey as itemkey_,
dt.iname as itemname,
dt.hsurl as httpstepurl,
dt.hsname as httpstepname,
dt.tcomments as triggercomments,
dt.tdescription as triggerdescription,
dt.tpriority as triggerpriority,
dt.eventclock as eventclock,
dt.eacknowledged as eventacknowledged
from
hosts h
inner join hosts_groups hg on h.hostid=hg.hostid
inner join groups g on hg.groupid = g.groupid
left join host_inventory hi on h.hostid=hi.hostid
LEFT JOIN
(SELECT
i.hostid as ihostid,
i.itemid as iitemid,
i.description as idescription,
i.key_ as ikey,
i.name as iname,
hs.url as hsurl,
hs.name as hsname,
t.description as tdescription,
t.url as turl,
t.comments as tcomments,
t.priority as tpriority,
from_unixtime(e.clock) as eventclock,
e.acknowledged as eacknowledged
from items i
left join functions f on i.itemid = f.itemid
left join triggers t on f.triggerid = t.triggerid
right join events e on t.triggerid = e.objectid
left join httpstepitem hsi on i.itemid = hsi.itemid
left join httpstep hs on hsi.httpstepid = hs.httpstepid
inner join problem p on e.eventid = p.eventid
WHERE
((e.acknowledged='0' AND i.status='0' AND r_clock='0') OR (e.acknowledged='1' AND i.status='0' AND r_clock='0'))
) dt ON h.hostid = dt.ihostid
where (h.status='2' or h.status='0');

Related

Select from SQL database information with newest revisions

I coding web app for my client and have issue with selecting from database raports with newest revisions.
SELECT
raports.*,
r1.*,
users.*,
(SELECT COUNT(*) FROM changes WHERE changes.changes_raports_id = raports.raports_id) as changes,
(SELECT changes.changes_date FROM changes WHERE changes.changes_raports_id = raports.raports_id ORDER BY changes.changes_date DESC LIMIT 1) as last_change,
(SUM(injuries.injuries_min_procent) / COUNT(injuries_to_raports.injuries_to_raports_id)) as min,
(SUM(injuries.injuries_max_procent) / COUNT(injuries_to_raports.injuries_to_raports_id)) as max
FROM raports
LEFT JOIN users
ON users.users_id = raports.raports_users_id
LEFT JOIN changes
ON changes.changes_raports_id = raports.raports_id
LEFT JOIN raports_to_changes r1
ON r1.raports_to_changes_raports_id = raports.raports_id
LEFT JOIN injuries_to_raports
ON injuries_to_raports.injuries_to_raports_raports_id = r1.raports_to_changes_raports_id
LEFT JOIN injuries
ON injuries_to_raports.injuries_to_raports_injuries_id = injuries.injuries_id
WHERE r1.raports_to_changes_changes_id = (SELECT max(raports_to_changes_changes_id) FROM raports_to_changes r2 WHERE r2.raports_to_changes_raports_id = r1.raports_to_changes_raports_id)
GROUP BY raports.raports_id ORDER BY raports.raports_id ASC;
In columns max and min i have not correct average from injuries. When i checked it and count all injuries i had 36 when true number is 2 but i have 18 revisions. So is logic that i have looped COUNT with all revisions but i want only the newest
I try changing WHERE statements and more LEFT JOINs but nothing helped.
Could someone fixed that code?
Thank you in advanced
Based on the clues revealed by your queries, the data model may look like this:
The select list shows that you need:
users information of a reports_id
aggregated injuries_min_procent and injuries_max_procent at raports_id level. (see cte_raport_injuries)
number of changes of a raports_id (see cte_raport_changes)
the last change_date of a raports_id (see cte_raport_changes)
I'm not sure about the need for raports_of_changes based on information revealed in the question, so I'm going to ignore it for now.
with cte_raport_injuries as (
select r.raports_id,
sum(i.injuries_min_procent) / count(*) as injuries_min_procent,
sum(i.injuries_max_procent) / count(*) as injuries_max_procent
from raports r
join injuries_to_raports ir
on r.raports_id = ir.injuries_to_raports_raports_id
join injuries i
on ir.injuries_to_raports_injuries_id = i.injuries_id
group by r.raports_id),
cte_raport_changes as (
select r.raports_id,
count(c.changes_id) as changes,
max(c.changes_date) as last_change
from raports r
join changes c
on r.raports_id = c.changes_raports_id
group by r.raports_id)
select u.users_id,
r.raports_id,
ri.injuries_min_procent,
ri.injuries_max_procent,
rc.changes,
rc.last_change
from raports r
join users u
on r.raports_users_id = u.users_id
join cte_raport_injuries ri
on r.raports_id = ri.raports_id
join cte_raport_changes rc
on r.raports_id = rc.raports_id;
The result looks like this:
users_id|raports_id|injuries_min_procent|injuries_max_procent|changes|last_change|
--------+----------+--------------------+--------------------+-------+-----------+
1| 11| 15.0000| 25.0000| 2| 2022-12-02|
So my question for you is what's in reports_to_changes that you need and what's its relationship between others? For further involvement from the community, you may want to share the following information in text format:
DDLs of each tables (primary key, foreign key, column names & data types)
Some representable sample data and basic business rules
Expected output

MySQL Creat View with all data where date is max

I want to create a view which combines the data with the maximal date from the tables shown in the picture. These should be grouped by the profileID.
Database ERM
The profileIDs are linked to profile.userID.
I tried different approches in my code. The fort one slects the data where date is max, but the join doesn't work. Every profileID will be joined with the same data.
CREATE
ALGORITHM = UNDEFINED
DEFINER = `b91788dd8d05b5`#`%`
SQL SECURITY DEFINER
VIEW fitchallengersql1.profileview AS
Select p.userID,
(SELECT
`bf`.`bodyFat`
FROM
(`fitchallengersql1`.`bodyfatprofile` `bf`
JOIN `fitchallengersql1`.`profile` `p`)
WHERE
((`bf`.`profileID` = `p`.`userID`)
AND (`bf`.`date` = (SELECT
MAX(`fitchallengersql1`.`bodyfatprofile`.`date`)
FROM
`fitchallengersql1`.`bodyfatprofile`)))) AS `bodyFat`,
(SELECT
`bw`.`bodyweight`
FROM
(`fitchallengersql1`.`bodyweightprofile` `bw`
JOIN `fitchallengersql1`.`profile` `p`)
WHERE
((`bw`.`profileID` = `p`.`userID`)
AND (`bw`.`date` = (SELECT
MAX(`fitchallengersql1`.`bodyweightprofile`.`date`)
FROM
`fitchallengersql1`.`bodyweightprofile`)))) AS `bodyWeight`,
(SELECT
`bmi`.`bmi`
FROM
(`fitchallengersql1`.`bmiprofile` `bmi`
JOIN `fitchallengersql1`.`profile` `p`)
WHERE
((`bmi`.`profileID` = `p`.`userID`)
AND (`bmi`.`date` = (SELECT
MAX(`fitchallengersql1`.`bmiprofile`.`date`)
FROM
`fitchallengersql1`.`bmiprofile`)))) AS `bmi`
From profile
In the second one the join works how it should, but I can't figure out a way to select just the data where date is max.
CREATE
ALGORITHM = UNDEFINED
DEFINER = `b91788dd8d05b5`#`%`
SQL SECURITY DEFINER
VIEW `fitchallengersql1`.`profileview` AS
SELECT
`p`.`userID` AS `userID`,
`p`.`privacy` AS `privacy`,
`bs`.`size` AS `bodysize`,
`bw`.`bodyweight` AS `bodyweight`,
`bf`.`bodyFat` AS `bodyfat`,
`bmi`.`bmi` AS `bmi`
FROM
((((`fitchallengersql1`.`profile` `p`
JOIN `fitchallengersql1`.`bodysizeprofile` `bs`)
JOIN `fitchallengersql1`.`bodyweightprofile` `bw`)
JOIN `fitchallengersql1`.`bmiprofile` `bmi`)
JOIN `fitchallengersql1`.`bodyfatprofile` `bf`)
WHERE
((`p`.`userID` = `bs`.`profileID`)
AND (`p`.`userID` = `bw`.`profileID`)
AND (`p`.`userID` = `bmi`.`profileID`)
AND (`p`.`userID` = `bf`.`profileID`))
Hope someone could help me.
Thank you!
fleewe
Hope following query gives what you need. Please follow the pattern and join the rest of the tables. Please note that when the table grows these will definitely have performance issues as this require huge processing.
-- Select the columns that you need
select p.*, lbp.*
from profile p
inner join (
-- get the latest bmiprofile per user profile
select bp1.*
from bmiprofile bp1
inner join (select profileID, max(date) as date from bmiprofile group by profileID) as bp2 on bp1.prfileId = bp2.profileId and bp1.date = bp2.date
) as lbp on lbp.ProfileId = p.userId
-- Join the other tables in similar way
this is only a comment, but I needed formating capability:
Don't place the joining predicates into the where clause if using ANSI join syntax, instead use ON followed by the relevant predicates. e.g.
FROM `fitchallengersql1`.`profile` `p`
JOIN `fitchallengersql1`.`bodysizeprofile` `bs` ON `p`.`userID` = `bs`.`profileID`
JOIN `fitchallengersql1`.`bodyweightprofile` `bw` ON `p`.`userID` = `bw`.`profileID`
JOIN `fitchallengersql1`.`bmiprofile` `bmi` ON `p`.`userID` = `bmi`.`profileID`
JOIN `fitchallengersql1`.`bodyfatprofile` `bf` ON `p`.`userID` = `bf`.`profileID`

Group By causing bug after Database restore

I am working on a rather complex and time critical data conversion.
This is achieved by using a Stored Procedure.
A recent change request required me to update this stored procedure. To do so in a safe manner, I have created a full schema dump including data and have imported this into two different schemas. One called 'original' and one called 'amended'.
Before updating the live database I am trying to compare the output of the original and amended database to identify the data that has been added and that none has been lost.
Unfortunately my test system is running MySQL v 5.7.12-0ubuntu-1 whereas my live server is a CentOS Server running 5.6.30.
A group clause in the original database (identical with live) is raising an issue (that does not exist on live). This error (1055 - Expression #5 of SELECT list is not in GROUP BY clause and contains non-aggregated column) makes total sense and is addressed in the revised database. I just want to run a comparison without having to install the exact same version of MySQL on this development server.
I have tried to remove ONLY_FULL_GROUP_BY from my sql_mode parameter and have matched the sql_mode on both servers to only NO_ENGINE_SUBSTITUTION
Can anyone help? The query is below:
Insert into skeleton_football (
sport_id,
parent_event_id,
event_id,
event_part_id,
back_outcome_id,
lay_outcome_id,
start_time,
market_type,
competition_name,
event_name,
event_part_name,
outcome_name,
outcome_value
)
SELECT
sp.id as `sport_id`,
if (ev.name is null, pev.id, null) as `parent_event_id`,
ev.id as `event_id`,
evp.id as `event_part_id`,
oc.back_outcome_id as back_outcome_id,
oc.lay_outcome_id as lay_outcome_id,
#oc.param_float_1,
#oc.param_float_2,
#oc.param_float_3,
#oc.param_boolean_1,
#oc.param_string_1,
#oc.param_participant_id_1,
#oc.param_participant_id_2,
#oc.param_participant_id_3,
#oc.param_event_part_id_1,
ev.start_time as start_time,
sp.name as market_type,
if (ev.name is null, pev.name, ev.name) as competition_name,
if (sp.name = "football",concat(epah.name, " v ", epaa.name),ev.name) as event_name,
evp.name as event_part_name,
oct.name as outcome_name,
get_outcome_value(
oct.name,
oc.param_participant_id_1,
max(epah.id),
max(epah.name),
max(epaa.id),
max(epaa.name),
opa.id,
opa.name,
oc.param_float_1,
oc.param_float_2,
oc.param_boolean_1
) as outcome_value
FROM raw_event ev
left join raw_event pev on pev.id = ev.parent_id
inner join raw_sport sp on ev.sport_id = sp.id
inner join config_events_filter cef on cef.sport_id = sp.id and (cef.competition_name is null or pev.name like cef.competition_name)
left join outcome_matched oc on ev.id = oc.event_id
inner join raw_event_part evp on evp.id = oc.event_part_id and evp.name in ("ordinary time", "whole match", "whole event")
cross join raw_participant_role prh on prh.name ="home"
cross join raw_participant_role pra on pra.name = "away"
cross join raw_participant_role pro on pro.name not in ("home", "away")
left join raw_event_participant_relation pera on pera.event_id = ev.id and pra.id = pera.participant_role_id
left join raw_event_participant_relation perh on perh.event_id = ev.id and prh.id = perh.participant_role_id
left join raw_event_participant_relation pero on pero.event_id = ev.id and pro.id = pero.participant_role_id
left join raw_outcome_type oct on oc.type_id = oct.id
left join raw_participant epaa on pera.participant_id = epaa.id
left join raw_participant epah on perh.participant_id = epah.id
left join raw_participant epao on pero.participant_id = epao.id
#left join raw_participant epap on per.participant_id = epap.id and pr.name not in ("home", "away")
left join raw_participant opa on oc.param_participant_id_1 = opa.id
where ev.start_time > date_sub('2016-05-11 14:00:00', INTERVAL 1 HOUR)
and ev.start_time < date_add('2016-05-11 14:00:00', INTERVAL 2 DAY)
group by sp.id, ev.id, evp.id, oc.back_unique, if (sp.name = "football",concat(epah.name, " v ", epaa.name),ev.name)
having event_name is not null;

Why is my SQL query not running?

Can someone help me, i don't know why my SQL script wont run? can any one see why?
Here it is
SELECT
vi.`id` as 'VehicleId', vi.`class_type` as 'VehicleClass',vi.`registration_number` as 'VehicleRegistrationNumber',
vr.`role_name` as 'VehicleRole',
vm.`name` as 'VehicleMake',
vmo.`name` as 'VehicleModel',
ud.`name` as 'Depot location',
WHERE vehicle_role = 'High Volume Jet Vac'
FROM
unify_rebuild.vehicle_information as vi
LEFT JOIN
unify_rebuild.vehicle_role as vr
ON
vi.unit_role = vr.role_id
LEFT JOIN
unify_rebuild.vehicle_manufacturer as vm
ON
vi.make = vm.id
LEFT JOIN
unify_rebuild.vehicle_model as vmo
ON
vi.model = vmo.id
LEFT JOIN
unify_rebuild.unify_depot as ud
ON
vi.depot_current_location = ud.id
I am trying to make one master table by joining data into the one so i can then display it on my web app, if anyone can see anything wrong i would greatly appreciate some pointers.
Have you tried to execute your query? I'm pretty sure that you'll receive some interesting errors in order to fix it.
The WHERE clause needs to be at the end of your query (after FROM and the JOINS) and you need to remove the last comma of your SELECT statement.
If you got still error's please check all the column names in your database or use "SELECT *. The where clause is also with the prefix "unify_rebuild." - maybe this helps:
SELECT
vi.id as 'VehicleId',
vi.class_type as 'VehicleClass',
vi.registration_number as 'VehicleRegistrationNumber',
vr.role_name as 'VehicleRole',
vm.name as 'VehicleMake',
vmo.name as 'VehicleModel',
ud.name as 'Depot location'
FROM
unify_rebuild.vehicle_information as vi
LEFT JOIN
unify_rebuild.vehicle_role as vr
ON
vi.unit_role = vr.role_id
LEFT JOIN
unify_rebuild.vehicle_manufacturer as vm
ON
vi.make = vm.id
LEFT JOIN
unify_rebuild.vehicle_model as vmo
ON
vi.model = vmo.id
LEFT JOIN
unify_rebuild.unify_depot as ud
ON
vi.depot_current_location = ud.id
WHERE
unify_rebuild.vehicle_role = 'High Volume Jet Vac'
SELECT vi.id VehicleId
, vi.class_type VehicleClass
, vi.registration_number VehicleRegistrationNumber
, vr.role_name VehicleRole
, vm.name VehicleMake
, vmo.name VehicleModel
, ud.name 'Depot location'
FROM vehicle_information vi
LEFT
JOIN vehicle_role vr
ON vi.unit_role = vr.role_id
AND vr.role_name = 'High Volume Jet Vac'
LEFT
JOIN vehicle_manufacturer vm
ON vi.make = vm.id
LEFT
JOIN vehicle_model vmo
ON vi.model = vmo.id
LEFT
JOIN unify_depot ud
ON vi.depot_current_location = ud.id

Assistance with MySQL Query - Omitting, Grouping?

Doing a bit of investigation and writing a query against a logs db.
I've joined a number of tables to bring back the data that I need, but i'd like to clean it up a bit.
The query returns all the users and which features they have enabled on their account.
Here is what i'm trying to do to clean it up:
Their is a column called 'actions' which has two states, 'added' and 'removed'
If a user feature has an action of 'removed' then I want to not show any of the rows for the same feature for that user which are also marked as 'added'
Is this possible?!
Here is what I have so far:
select users.id as site_id, users.company_name, feature_log.featurecode, feature.minimum_account as feature_type, users.account_type as site_type, account_types.name as account, feature_log.action, feature_log.time
from users
inner join
feature_log
on users.id = feature_log.siteid
inner join
feature
on feature_log.featurecode = feature.featurecode
inner join account_types
on users.account_type_INC = account_types.id
where feature.minimum_account != 0
AND feature.minimum_account > users.account_type
AND users.status = 'Y'
ORDER BY feature_log.time DESC
Thanks for any support!
So, in order to "mute" all the features, that have been "removed" at any point in time for a given user, you can add a (left) join on the following subquery:
SELECT DISTINCT users.id as siteid, feature_log.featurecode, TRUE as mute_feature
FROM users
INNER JOIN feature_log ON (users.id = feature_log.siteid)
WHERE action = 'removed'
This will be the list of features that a given user disabled at some point in time. Then in your query's WHERE clause, you'd add a filter like so:
AND NOT IFNULL(mute_feature, FALSE)
Essentially, that'd bring your whole query to be:
select users.id as site_id, users.company_name, feature_log.featurecode, feature.minimum_account as feature_type, users.account_type as site_type, account_types.name as account, feature_log.action, feature_log.time
from users
inner join
feature_log
on users.id = feature_log.siteid
left join (
SELECT DISTINCT users.id as siteid, feature_log.featurecode, TRUE as mute_feature
FROM users
INNER JOIN feature_log ON (users.id = feature_log.siteid)
WHERE action = 'removed'
) as muted_features ON (feature_log.siteid = muted_features.siteid AND feature_log.featurecode = muted_features.featurecode)
inner join
feature
on feature_log.featurecode = feature.featurecode
inner join account_types
on users.account_type_INC = account_types.id
where feature.minimum_account != 0
AND feature.minimum_account > users.account_type
AND users.status = 'Y'
AND NOT IFNULL(mute_feature, FALSE)
ORDER BY feature_log.time DESC