I'm sure someone will have a very simple answer to this but I can't work it out for the life of me: I have 3 tables that look something like this:
Vehicles: Vehicle_id, Reg_number...
Datalogger: Logger_id, event, status, date...
Vehicle_Loggers: Vehicle_id, Logger_id, installed_from, installed_to
(Relationships are on columns with the same name here)
Using these tables how would I get the whole history of a given vehicle's logs (event and status) even if it has had multiple loggers fitted at different times?
I know this can be done using a cursor but as this is really a set operation (Get the set of loggers that have been attached to the vehicle, then get the reports of each logger using the given date range for that logger)
EDIT: Loggers can be used in more than one vehicle during their lifetime, hence the inclusion of the dates.
Thanks
Gareth
You can do it like this:
select v.Reg_number, d.* from Vehicles v
inner join Vehicle_Loggers vl on vl.Vehicle_id = v.Vehicle_id
inner join Datalogger d on d.Logger_id = vl.Logger_Id
where v.Reg_number = ...
Just replace the Reg_number for the intended one.
To take in account the dates, possibly would be like this:
select v.Reg_number, d.* from Vehicles v
inner join Vehicle_Loggers vl on vl.Vehicle_id = v.Vehicle_id
inner join Datalogger d on d.Logger_id = vl.Logger_Id and d.date between vl.installed_from and vl.installed_to
where v.Reg_number = ...
Related
I don't know a lot about MyQSL.
Here is my code (to extract code from a monitoring tool)
SELECT DISTINCT
FROM_UNIXTIME(data_bin.ctime), index_data.host_name, index_data.service_description, metrics.metric_name, data_bin.value
FROM metrics
inner join index_data ON index_data.id = metrics.index_id
inner join data_bin ON data_bin.id_metric = metrics.metric_id
ORDER BY data_bin.ctime;
Despites my efforts, I don't manage to :
Filter by timerange (with human readable time)
Obtain that output :
Timerange, Hostname, ServiceA, metricA1, metricA2, ... ServiceB, metricB1, metricB2 ...
-> the goal is to group by identical Timerange and Hostname
I think your question is missing some key points, and I'll adjust this if you can specify what you're looking for a bit better with some example data from each of these tables.
But in the meantime, I think I have a good understanding, maybe this is what you're looking for:
SELECT DISTINCT
FROM_UNIXTIME(data_bin.ctime) AS timerange, index_data.host_name, index_data.service_description, metrics.metric_name, data_bin.value
FROM metrics
inner join index_data ON index_data.id = metrics.index_id
inner join data_bin ON data_bin.id_metric = metrics.metric_id
GROUP BY index_data.host_name, timerange
ORDER BY timerange;
Can anybody help me figure out how to write the following SQL statement in Rails?
SELECT * FROM shifts a
INNER JOIN (
SELECT shifts.date, shifts.time, max(shifts.barber_id) as 'barber_id'
FROM shifts
WHERE shifts.date = '2017-09-06' and shifts.is_free = true
GROUP BY shifts.date, shifts.time
) b
ON a.date = b.date AND a.time = b.time AND a.barber_id = b.barber_id
WHERE a.`is_free` = true AND a.date = '2017-09-06'
Because where-conditional is the same in subquery and main query I'm using a scope as following:
scope :available, -> { where('shifts.is_free', true).where('shifts.date', '2017-09-06').order(date: :desc, time: :asc) }
I've also created the scope for subquery:
scope :grouped_shifts, -> { select("date, time, max(barber_id) as barber_id").group(:date, :time).available }
but I can't find out how to chain the scope to join method. Can I pass it as argument? Like that:
scope :something, -> { joins(self.grouped_shifts).available }
Or I shouldn't use scopes in this case?
Thanks for help in advance!
Piecing together what you have said in your question and in your first comment on your question, I gather you are trying to do this:
There are many barbers, each with many shifts. Each shift has a date and a time, and each barber may be available or not available on any given shift.
You want to find, for each time slot on 2017-09-06 that has at least one available barber, which barber available in that time slot has the largest id (ordered by time slot)
This is how you do it:
Shift.where(date: '2017-09-06').where(is_free: true).order(:time).group(:time).maximum(:barber_id)
You don't need to group by date, since all the shifts selected will be on the same date. If you wanted to extend this over all dates in the table, then it would look like this:
Shift.where(is_free: true).order(:date, :time).group(:date, :time).maximum(:barber_id)
I have a problem which I cant figure out, and have looked on google and similar questions on here, but they are just not quite the same.
I am trying to build a MySQL Query which has two parts, the first is easy and i have done this fine, as it uses existing relationships, see...
SELECT
clientsites.SiteName,
clients.ClientName,
pafaddresses.PostTown,
pafaddresses.PostCode,
CONCAT("XXXXXXX", Replace(UPPER(pafaddresses.PostCode),' ','')) AS JouneyKeytemp,
clientsites.SiteType
FROM clientsites
INNER JOIN clients ON clientsites.ClientFk = clients.ClientPk
INNER JOIN pafaddresses ON clients.ActualPAF = pafaddresses.id
You will see from this code that an alias is generated which concats two postcodes and looks like xxxxxxxyyyyyy, this does work but for obvious reasons ive removed the actual postcodes.
What I now what to do is to bring in two fields from an unrelated table called Journeys:
SELECT
JourneyKey,
SingleDistance,
SingleTime
FROM journeys
I want to bring in SingleDistance and SingleTime, where the Journey Key = Generated Alias of JourneyKeyTemp.
I have tried adding the following:
INNER JOIN journeys ON JouneyKeytemp = journeys.JourneyKey
But I just keep getting a syntax error.
Any help would be appreciated.
Repeat the expression in join predicate:
INNER JOIN journeys
ON CONCAT("XXXXXXX", Replace(UPPER(pafaddresses.PostCode),' ','')) = journeys.JourneyKey
Or you can create a subquery:
select * from(
SELECT
clientsites.SiteName,
clients.ClientName,
pafaddresses.PostTown,
pafaddresses.PostCode,
CONCAT("XXXXXXX", Replace(UPPER(pafaddresses.PostCode),' ','')) AS JouneyKeytemp,
clientsites.SiteType
FROM clientsites
INNER JOIN clients ON clientsites.ClientFk = clients.ClientPk
INNER JOIN pafaddresses ON clients.ActualPAF = pafaddresses.id)t
INNER JOIN journeys ON t.JouneyKeytemp = journeys.JourneyKey
http://sqlfiddle.com/#!3/3ec1f/119
Here's my fiddle...I want the result to look like this but the query I'm using doesn't do that:
My problem with the query is that I can't seem to exclude "The Kingdom of the Crystal Skull" using the exclusion_flag condition. I also don't know why it seems that Contract 3 (Raiders of the Lost Arc) is not showing up either. I have been toiling with this for hours and have no idea what the problem is. I tried looking into subqueries, but I'm not sure that's the solution...
There's a couple of questions/issues there so I'll try to address them individually.
1) You can't exclude "The Kingdom of the Crystal Skull" using the exclusion_flag because contract_sid 7 and 8 both refer to product_list_sid 3 which includes "The Kingdom of the Crystal Skull" - you would need to create a separate product_list_sid if you wanted a contract which excluded it.
2) "Raiders of the Lost Arc" (contract_sid 3) isn't showing up because it's a "single product" contract, and your query only joins from scope to product_list_join using product_list_id - contract_sid 3 is in the product_sid column so you need a separate join to cater for contracts that use product_sid instead of product_list_sid (I assume that a contract can't use both). This is a pretty dodgy schema design but here's a query that solves that issue. Notice the use of LEFT OUTER JOIN to indicate that the table being joined to might not contain any rows (for example when scope.product_list_sid is NULL but scope.product_sid is not).
SELECT s.contract_sid,
c.contract_description,
ISNULL(p.product_description, p2.product_description) AS product_description
FROM scope s
JOIN contracts c ON (c.contract_sid = s.contract_sid)
LEFT OUTER JOIN
product_list_join plj ON (plj.product_list_sid = s.product_list_sid)
LEFT OUTER JOIN
products p ON (p.product_sid = plj.product_sid)
LEFT OUTER JOIN
products p2 ON (p2.product_sid = s.product_sid)
WHERE s.exclusion_flag = 'N'
ORDER BY s.contract_sid;
Here's the SQLFiddle for my solution: http://sqlfiddle.com/#!3/fc62e/10
Edit: After posting this I realised what you're actually trying to do - the scope table not only provides the details of contracts but also provides specific products to exclude from contracts. Again, this is bad schema design and there should be a separate scope_exclusions table or something, but here's a query that does that and excludes "The Kingdom of the Crystal Skull" as requested:
SELECT inner_query.contract_description,
inner_query.product_description
FROM (
SELECT s.contract_sid,
c.contract_description,
ISNULL(p.product_sid, p2.product_sid) AS product_sid,
ISNULL(p.product_description, p2.product_description) AS product_description
FROM scope s
JOIN contracts c ON (c.contract_sid = s.contract_sid)
LEFT OUTER JOIN
product_list_join plj ON (plj.product_list_sid = s.product_list_sid)
LEFT OUTER JOIN
products p ON (p.product_sid = plj.product_sid)
LEFT OUTER JOIN
products p2 ON (p2.product_sid = s.product_sid)
WHERE s.exclusion_flag = 'N'
) inner_query
WHERE NOT EXISTS ( SELECT 1
FROM scope
WHERE exclusion_flag = 'Y'
AND contract_sid = inner_query.contract_sid
AND product_sid = inner_query.product_sid )
ORDER BY inner_query.contract_description;
SQL Fiddle: http://sqlfiddle.com/#!3/fc62e/14
I have a report in Access 2013 that prints an equipment log. There is a bunch of dates listed for each piece of equipment. I wanted to only print the newest date for each piece of equipment. I have searched the internet and this site with no luck. So any suggestions will be greatly appreciated.
My SQL statement is:
SELECT dbo_eq_location_transfer_d.equipment_id, dbo_equipment.description, dbo_eq_location_transfer_d.transaction_no, dbo_eq_location_transfer_d.job_no, dbo_jobs.description, dbo_eq_location_transfer_d.date_booked, dbo_eq_location_transfer_d.delivery_time, dbo_eq_location_transfer_d.line_no, dbo_eq_location_transfer_d.row_modified_by, dbo_eq_location_transfer_d.comment
FROM (dbo_eq_location_transfer_d INNER JOIN dbo_jobs ON dbo_eq_location_transfer_d.job_no = dbo_jobs.job_no) INNER JOIN dbo_equipment ON dbo_eq_location_transfer_d.equipment_no = dbo_equipment.equipment_no
ORDER BY dbo_eq_location_transfer_d.equipment_id, dbo_eq_location_transfer_d.transaction_no;
The date_booked field is the date field I am trying narrow down. I have a simple SQL query that works and I have been trying copy that into the about SQL but cannot seem to get it to mesh. It is:
SELECT [dbo_eq_location_transfer_d.equipment_no], Max(dbo_eq_location_transfer_d.date_booked) AS ["Newest Date"]
FROM dbo_eq_location_transfer_d
GROUP BY [dbo_eq_location_transfer_d.equipment_no];
In your query set the date fields criteria to:
>Now()-30
This will show any dates for the last 30 days just change 30 to the number of days you want to see.
Now that I understand your structure & data, here is what I did:
(1) Create the following query to select only the most recent 'date_booked' for each 'equipment_no'; save the query with name '23020071_A':
SELECT dbo_eq_location_transfer_d.equipment_no,
First(dbo_eq_location_transfer_d.transaction_no) AS FirstOftransaction_no,
First(dbo_eq_location_transfer_d.job_no) AS FirstOfjob_no,
First(dbo_eq_location_transfer_d.date_booked) AS FirstOfdate_booked
FROM (dbo_eq_location_transfer_d
INNER JOIN dbo_jobs ON dbo_eq_location_transfer_d.job_no = dbo_jobs.job_no)
INNER JOIN dbo_equipment ON dbo_eq_location_transfer_d.equipment_no = dbo_equipment.equipment_no
GROUP BY dbo_eq_location_transfer_d.equipment_no
ORDER BY First(dbo_eq_location_transfer_d.date_booked) DESC;
(2) I created the following query combining the new query with your existing query:
SELECT dbo_eq_location_transfer_d.equipment_id, dbo_equipment.description,
dbo_eq_location_transfer_d.transaction_no, dbo_eq_location_transfer_d.job_no,
dbo_jobs.description, dbo_eq_location_transfer_d.date_booked,
dbo_eq_location_transfer_d.delivery_time, dbo_eq_location_transfer_d.line_no,
dbo_eq_location_transfer_d.row_modified_by, dbo_eq_location_transfer_d.comment
FROM 23020071_A INNER JOIN ((dbo_eq_location_transfer_d
INNER JOIN dbo_jobs ON dbo_eq_location_transfer_d.job_no = dbo_jobs.job_no)
INNER JOIN dbo_equipment ON dbo_eq_location_transfer_d.equipment_no = dbo_equipment.equipment_no)
ON ([23020071_A].FirstOftransaction_no = dbo_eq_location_transfer_d.transaction_no)
AND ([23020071_A].equipment_no = dbo_eq_location_transfer_d.equipment_no)
AND ([23020071_A].FirstOfjob_no = dbo_eq_location_transfer_d.job_no)
ORDER BY dbo_eq_location_transfer_d.equipment_id, dbo_eq_location_transfer_d.transaction_no;
Now when I run the second query, it returns only the most recent row for that piece of equipment.