MySQL can I in a join calculate and show the results - mysql

I have 2 tables in the first I define the equipment possible like fire hydrant or fire alarm system, all of theese are to check within a certain time, in this table I have the name of theese equipments and the time within they are to chec, in the second table I have the date when the last chec was I want create a View List but that contains the information, when the next chec is to realize,
Like this
Create View listafacilitymanagemen AS
SELECT DISTINCT ID, tipo, posicion, checeo, checeo + checeointerval,
JOIN ID, tipo, checeointerval
FROM hotel.facilitymanagemen_equipo
ORDER BY checeo + checeointerval;
My database is very big and I don't want this in another column in the the table "facilitymanagement".

I trust very much in w3school, there I found this https://www.w3schools.com/sql/sql_join_inner.asp.
CREATE VIEW TABLE facilitymanagement
SELECT m.ID,
m.tipo,
e.tipo,
e.ID,
m.posicio,
m.checeo,
m.checeo + e.checeointerval,
m.checeocontrollado,
m.checeooficial,
m.checeooficial + e.checeooficialinterval,
m.checeooficialcontrollado,
m.controllero,
e.checeointerval,
e.checeooficialinterval
FROM hotel.facilitymanagemen (m)
INNER JOIN hotel.facilitymanagement_equipment (e)
ON m.tipo = e.ID
ORDER BY m.checeooficial + e.checeooficialinterval;
I'm a german and by law we are to chec the equipments in a building that has to do with fire to chec by a specialist and a responsable authority, moreover we have for everything an insurance and if the interval are exceeded they don't pay, so this View list is very important, I added some columne aboveall "checeooficial" and this columne with the interval give the ORDER BY criteria.
If my code works I cannot try.

Because I have 2 data bases I precise from whitch one I want the data in the FROM and the INNER JOIN clause it is the data base "hotel".

I added a WHERE claus to filter the lines, so the VIEW TABLE contains only the data after the actual system-date and I ORDERed DESC; so the most urget equipment apears first.
CREATE VIEW TABLE facilitymanagement AS
SELECT m.ID,
m.tipo,
e.tipo,
e.ID,
m.posicio,
m.checeo,
m.checeo + e.checeointerval,
m.checeocontrollado,
m.checeooficial,
m.checeooficial + e.checeooficialinterval,
m.checeooficialcontrollado,
m.controllero,
e.checeointerval,
e.checeooficialinterval
FROM hotel.facilitymanagemen (m)
INNER JOIN hotel.facilitymanagement_equipment (e)
ON m.tipo = e.ID
WHERE m.checeooficial + e.checeooficialinterval > NOW()
ORDER BY m.checeooficial + e.checeooficialinterval DESC;
Instead of NOW() better would be to call the CURDATE()-function.

Related

How to transform SQL code into a measure?

Right now i am using 3 CSV files ( appointment, Person and Referral ) to calculate what i have called as KPI4, KPI5 and KPI6.
I import them into an Access Database that run some SQL queries. I want to automate this proces a bit and create a measure for these KPI's and just upload/update the 3 csv files and the POWER BI report just get updated.
For example for KPI4 I have the following SQL's queries
First and the main one but which refers to z_KPI8_part1 :
SELECT
Person.LPTID, Person.ccgName, Person.Caseload, t1.FTDate,
t1.SERVICEID, Person.LTCondition, Referral.Caseload, *
FROM
Person
INNER JOIN ((SELECT SERVICEID,FTDate
FROM z_KPI8_part1) AS t1
INNER JOIN Referral
ON t1.SERVICEID = Referral.SERVICEID)
ON Person.LPTID = Referral.LPTID;
z_KPI8_part1 which referrs to z_FirstTreatmentDate :
SELECT
z_FirstTreatmentDate.SERVICEID, Min(z_FirstTreatmentDate.FTDate) AS FTDate,
Max(Appointment.ATTENDANCE) AS ATTENDANCE
FROM
Appointment
INNER JOIN z_FirstTreatmentDate
ON (Appointment.SERVICEID = z_FirstTreatmentDate.SERVICEID) AND
(Appointment.Appointment = z_FirstTreatmentDate.FTDate)
WHERE
(((z_FirstTreatmentDate.FTDate) Between [forms]![frmMain]![txtFTDateFrom] And
[forms]![frmMain]![txtFTDateTo]))
GROUP BY
z_FirstTreatmentDate.SERVICEID;
z_FirstTreatmentDate :
SELECT
Appointment.SERVICEID, Min(Appointment.APPOINTMENT) AS FTDate,
Min(Appointment.APPTYPE) AS APPTYPE
FROM
(SELECT *
FROM Appointment
WHERE
(Appointment.APPTYPE=02 OR Appointment.APPTYPE=03 OR Appointment.APPTYPE=05) AND
(Appointment.ATTENDANCE='5' OR Appointment.ATTENDANCE='6')
) AS [%$###_Alias]
GROUP BY
Appointment.SERVICEID;
In theory KPI4 is First Appointment Date when client's Session Type ( APPTYPE )is one of the following: 2,3,5
And
Attendance Status is one of the following: 5 and 6.
From my method i am not getting anywhere near the numbers i get from Access database.
Please help me or guide me

How select count distinct (unique truckers) without group by function and maybe without using Having (not sure about last)

I have a task, but couldn't solve it:
There are truckers and they have to travel between cities.
We have data of these travels in our database in 2 tables:
trucker_traffic
tt_id (key)
date
starting_point_coordinate
destination_coordinate
traveller_id
event_type ('travel', 'accident')
parent_event_id (For 'accident' event type it's tt_id of the original travel. There might be few accidents within one travel.)
trucker_places
coordinate (key)
country
city
I need SQL query to pull the number of all unique truckers who travelled more than once from or to London city in June 2020.
In the same query pull the number of these travels who got into an accident.
Example of my tries
SELECT
count(distinct(tt.traveller_id)),
FROM trucker_traffic tt
JOIN trucker_places tp
ON tt.starting_point_coordinate = tp.coordinate
OR tt.destination_coordinate = tp.coordinate
WHERE
tp.city = 'London'
AND month(tt.date) = 6
AND year(tt.date) = 2020
GROUP BY tt.traveller_id
HAVING count(tt.tt_id) > 1
But it's select count distinct truckers with grouping and works only if I had one tracker in db
For second part of task (where I have select number of travels with accident - I think that good to use function like this
SUM(if(count(tt_id = parent_event_id),1,0))
But I'm not sure
This is rather complicated, so make sure you do this step by step. WITH clauses help with this.
Steps
Find travels from and to London in June 2020. You can use IN or EXISTS in order to see whether a travel had accidents.
Group the London travels by traveller, count travels and accident travels and only keep those travellers with more than one travel.
Take this result set to count the travellers and sum up their travels.
Query
with london_travels as
(
select
traveller_id,
case when tt_id in
(select parent_event_id from trucker_traffic where event_type = 'accident')
then 1 else 0 end as accident
from trucker_traffic tt
where event_type = 'travel'
and month(tt.date) = 6
and year(tt.date) = 2020
and exists
(
select
from trucker_places tp
where tp.coordinate in (tt.starting_point_coordinate, tt.destination_coordinate)
and tp.city = 'London'
)
)
, london_travellers as
(
select
traveller_id,
count(*) as travels,
sum(accident) as accident_travels
from london_travels
group by traveller_id
having count(*) > 1;
)
select
count(*) as total_travellers,
sum(travels) as total_travels,
sum(accident_travels) as total_accident_travels
from london_travellers;
If your MySQL version doesn't support WITH clauses, you can of course just nest the queries. I.e.
with a as (...), b as (... from a) select * from b;
becomes
select * from (... from (...) a) b;
You say in the request title that you don't want GROUP BY in the query. This is possible, but makes the query more complicated. If you want to do this I leave this as a task for you. Hint: You can select travellers and count in subqueries per traveller.

msAccess query with Sum and extra criteria

I need to get all of the Costs values for a Dog in a specific month. When I use this code with Access it says the join operation is not supported. Is there a better way to accomplish this in MS Access? I need all of the dog names to come back even if they don't have a cost associated with them for a specific month
Select Dog.DogName, Dog.DogOwner, Sum(Costs.CostAmount)
From
(Dog Left join Costs on Dog.DogName = Costs.DogName and Costs.CostMonth = 10)
Group by Dog.DogName, Dog.OwnerName
Try this:
Select
Dog.DogName, Dog.DogOwner, Sum(Costs.CostAmount) As TotalAmount
From
Dog
Left join
Costs
On
(Dog.DogName = Costs.DogName)
Where
Costs.CostMonth <= Month(Date())
Or
Costs.CostMonth Is Null
Group by
Dog.DogName, Dog.OwnerName
SELECT Dogs.DogName
, Dogs.OwnerName
, (
SELECT SUM(Costs.CostAmountAmount)
FROM Costs
WHERE Dogs.DogName = Costs.DogName AND
Costs.CostMonth =NumMonth
)
FROM Dogs;

SQL get count from table 1 where complicated

I am stuck with a sql code where i need te get data as followed(i hope i can explain it good enough):
There are three tables in my database:
Table 1 is filled with traffic accidents(VKL_NUMBER and TIME)
Table 2 is filled with the locations of the accidents and the closest weather station (VKL_NUMBER, LOCATION and STN_NUMBER )
Table 3 is filled with weather data and the weather station where it came from(STN_NUMBER, TIME, WEATHER_TYPE)
I need to count the amount of accidents where it rains.
The keys to the tables are:
From 1 to 2: VKL_NUMBER(accident number)
From 2 to 3: STN_NUMBER (weather station number)
How can i get the weathertype at the time and closest to the accident in a count
Like :
Count accidents where it rains at the closest weatherstation.
for more info:
The accidents table has VKL_NUMBER(FK to the locations table) TIME(HHMM format) and DATE(YYMMDD format)
The locations table has VKL_NUMBER(FK to accidents), LOCATION(not important for this question) and STN_NUMBER(FK to the weather table)
The weather table had STN_NUMBER(FK to locations table), WEATHERTYPE("rain","snow","hail" ), TIME(HHMM format) and DATE(YYMMDD format)
/* apparently you'll need to combine and cast the <date + time> values */
select count(case when weather.weathertype = 'rain' then 1 end)
from
(
select
accidents.vkl_number,
min(<accidents.date + accidents.time>) as time_of_accident,
min(weather.stn_number) as stn_number,
max(timestampdiff(minute,
<weather.date + weather.time>,
<accidents.date + accidents.time>
)) as differential
from
t1 accidents inner join t2 accident_locations
on accident_locations.vkl_number = accidents.vkl_number
inner join t3 weather
on weather.stn_number = accident_locations.stn_number
and weather.time <= accidents.time
group by accidents.vkl_number
) closest
inner join t3 weather
on weather.stn_number = closest.stn_number
and date_add(
<weather.date + weather.time>,
interval differential second
) = closest.time_of_accident
I'm assuming you want the station time just prior to the accident. Breaking ties is a significant complication and we need more info about your desired matching logic.

MySQl count grouping by 4 columns

Basically, this query returns me different values from counts()
Geographic Address(city),Office,Device type, Device unique type identifier, number case by device type
0001,1002,ORDENADOR,ORD1234,5 INCIDENCIAS
0001,1002,ORDENADOR,ORD3333,2 INCIDENCIAS
0001,1002,ORDENADOR,ORD2222,1 INCIDENCIAS
0001,1002,TECLADO,TECYYYY,2 INCIDENCIAS
0001,1002,TECLADO,TECXXXX,4 INCIDENCIAS
0001,1002,PANTALLA,PAN0000,1 INCIDENCIAS
Select
d.dt as 'Direccion Territorial',
t.centro as 'Oficina',
nombrelargo,
if(length(p.Oficina)=3,concat('0',p.Oficina),p.Oficina) as 'Oficina2',
p.Tipo_Disp as 'Dispositivo',
count(p.Tipo_Disp) as 'Nº de partes/Etiqueta',
p.Etq_Amarilla as 'Etiqueta',
------------ count(TOTAL INC DE ESE DISPOSITIVO) ---------------------------,
------------ count(TOTAL INC DE ESA OFICINA) ---------------------------
from textcentro t,dtdz d,ppp p
where
t.jcentro03=d.dt and
t.organizativo='OFIC./AGEN./DELEG.' and
t.situacion='ABIERTO' and
t.sociedad='0900' and
(p.Estado != "Abierto" and p.Estado!= 'Planificado') and
(month(p.Fecha_y_hora_de_creacion) = 8 and year(Fecha_y_hora_de_creacion)=2013) and
t.centro=if(length(p.Oficina)=3,concat('0',p.Oficina),p.Oficina)
GROUP BY d.dt,t.centro,p.Tipo_Disp,p.Etq_Amarilla
The grouping:
1 - d.dt ----> Postal code
2 - t.centro ----> Office code
3 - p.Tipo_Disp ----> Device Type
4 - d.Etq_Amarilla ----> Unique identifier for this device
The tables are :
1- textcentro ----> Specific information of the offices
2- dtdz ----> auxiliary table to find the Postal Code of the office
3- ppp ----> Table where we can find all the cases
So now, I want to sum the total number of cases by device type, should be this:
Postal Code,Office,Device type, Unique identifier for Device, total number of cases by unique identifier device, total number case by device type, total number case by office
0001,1002,ORDENADOR,ORD1234,5 INCIDENCIAS,8 INC,15
0001,1002,ORDENADOR,ORD3333,2 INCIDENCIAS,8 INC,15
0001,1002,ORDENADOR,ORD2222,1 INCIDENCIAS,8 INC,15
0001,1002,TECLADO,TECYYYY,2 INCIDENCIAS,6 INC,15
0001,1002,TECLADO,TECXXXX,4 INCIDENCIAS,6 INC,15
0001,1002,PANTALLA,PAN0000,1 INCIDENCIAS,1 INC,15
I'm trying with sums and counts functions but i dont reach it, i don't have any way to take the last two columns. I think that i can try to take this number by sub-query in the column but the performance will be down too much.
The example would be this... but even i get to finish the query and im waiting around 12-13 minutes.
Select
d.dt as 'Direccion Territorial',
t.centro as 'Oficina',
nombrelargo,
if(length(p.Oficina)=3,concat('0',p.Oficina),p.Oficina) as 'Oficina2',
p.Tipo_Disp as 'Dispositivo',
count(p.Tipo_Disp) as 'Nº de partes/Etiqueta',
p.Etq_Amarilla as 'Etiqueta',
(Select count(*) from People_DB pp where pp.Oficina=p.Oficina and pp.Tipo_Disp=Dispositivo and (month(pp.Fecha_y_hora_de_creacion) = 8 and year(pp.Fecha_y_hora_de_creacion)=2013) and (pp.Estado != "Abierto" and pp.Estado!= 'Planificado') )
from textcentro t,dtdz d,ppp p
where
t.jcentro03=d.dt and
t.organizativo='OFIC./AGEN./DELEG.' and
t.situacion='ABIERTO' and
t.sociedad='0900' and
(p.Estado != "Abierto" and p.Estado!= 'Planificado') and
(month(p.Fecha_y_hora_de_creacion) = 8 and year(Fecha_y_hora_de_creacion)=2013) and
t.centro=if(length(p.Oficina)=3,concat('0',p.Oficina),p.Oficina)
GROUP BY d.dt,t.centro,p.Tipo_Disp,p.Etq_Amarilla
Sorry for my poor english, maybe this post is unintelligible
May I make some suggestions:
First, your choice of tables looks like this:
from textcentro t,dtdz d,ppp p
For the sake of clarity I suggest you employ explicit JOIN statements instead. For example
FROM textcentro AS t
JOIN dtdx AS d ON t.jcentro03=d.dt
JOIN ppp AS p ON XXXXXXXXX
You may want to use LEFT JOIN in cases for example, where there might be no corresponding row in dtdx to go with a row in textcentro.
I cannot tell from your sample query what the ON constraint for the JOIN to ppp should be. I have shown that with XXXXXXXXX in my code above. I think your condition is this:
t.centro=if(length(p.Oficina)=3,concat('0',p.Oficina),p.Oficina)
but that is a nasty expression to compute, and therefore very slow. It looks like your t.centro is a char column containing an integer with leading zeros, and your p.Oficina is the same but without the leading zeros. Instead of adding the leading zero to p.Oficina, try stripping it from the t.centro column.
CAST(t.centro AS INTEGER) = p.Oficina
Keep in mind that without a simple JOIN constraint you get a combinatorial explosion: m times n rows. This makes things slow and possibly wrong.
So, your table selection becomes:
FROM textcentro AS t
JOIN dtdx AS d ON t.jcentro03=d.dt
JOIN ppp AS p ON CAST(t.centro AS INTEGER) = p.Oficina
Second, your date/time search expressions are not built for speed. Try this:
p.Fecha_y_hora_de_creacion >= '2013-08-01'
AND p.Fecha_y_hora_de_creacion < '2013-08-01' + INTERVAL 1 MONTH
If you have an index on your p.Fecha... column, this will permit a range-scan search on that column.
Third, this item in your SELECT list is killing performance.
(Select count(*)
from People_DB pp
where pp.Oficina=p.Oficina
and pp.Tipo_Disp=Dispositivo
and (month(pp.Fecha_y_hora_de_creacion) = 8
and year(pp.Fecha_y_hora_de_creacion)=2013)
and (pp.Estado != "Abierto" and pp.Estado!= 'Planificado') )
Refactor this to be a virtual table in your JOIN list, as follows.
(SELECT COUNT(*) AS NumPersonas,
Oficina,
Tipo_Disp
FROM People_DB
WHERE Fecha_y_hora_de_creacion >= '2013-08-01'
AND Fecha_y_hora_de_creacion < '2013-08-01' + INTERVAL 1 MONTH
AND Estado != 'Abierto'
AND Estado != 'Planificado
GROUP BY Oficina, Tipo_Disp
) AS pp_summary ON ( pp_summary.Oficina=p.Oficina
AND pp_summary.Tipo_Disp=Dispositivo)
So, this is your final list of tables.
FROM textcentro AS t
JOIN dtdx AS d ON t.jcentro03=d.dt
JOIN ppp AS p ON CAST(t.centro AS INTEGER) = p.Oficina
JOIN (
SELECT COUNT(*) AS NumPersonas,
Oficina,
Tipo_Disp
FROM People_DB
WHERE Fecha_y_hora_de_creacion >= '2013-08-01'
AND Fecha_y_hora_de_creacion < '2013-08-01' + INTERVAL 1 MONTH
AND Estado != 'Abierto'
AND Estado != 'Planificado
GROUP BY Oficina, Tipo_Disp
) AS pp_summary ON ( pp_summary.Oficina=p.Oficina
AND pp_summary.Tipo_Disp=Dispositivo)
Three of these tables are "physical" tables, and the fourth is a "virtual" table, constructed as a summary of the physical table called People_DB.
You can include
pp_summary.NumPersonas
in your SELECT list.
Fourth, avoid the nonstandard extensions to MySQL GROUP BY functionality, and use standard SQL. Read this for more information.
http://dev.mysql.com/doc/refman/5.0/en/group-by-extensions.html
Fifth, add appropriate indexes to your tables.