Find value based on same row values - sql

I have a database with a table (tblPersonnel) that is populated with following data.
Name_Personnel VesselName SailoutDate Time_transfer Direction
JB Flight 2 3/03/2016 10:38:00 UP
MH Flight 2 3/03/2016 10:38:00 UP
RS Flight 2 3/03/2016 10:38:00 UP
JB Flight 2 3/03/2016 11:40:00 DOWN
MH Flight 2 3/03/2016 11:40:00 DOWN
RS Flight 2 3/03/2016 11:40:00 DOWN
I need to query the total time for all personnel between the "UP" and "DOWN" time.
I'd like to come with a output like this.
Name_Personnel VesselName SailoutDate Time_transfer_UP Time_transfer_DOWN Total_time
JB Flight 2 3/03/2016 10:38:00 11:40:00 01:02
MH Flight 2 3/03/2016 10:14:00 11:49:00 01:35
RS Flight 2 3/03/2016 10:36:00 11:53:00 01:17
The Name_personnel, vesselname and sailoutdate always have an "UP" and a "Down" value. So these can be used to search matching rows.
How can I do this?

You can use conditional aggregation. The challenge is the total time. If you can live with total minutes, then it is pretty easy:
select Name_Personnel, VesselName, SailoutDate,
max(iif(direction = 'UP', time_transfer, NULL)) as time_transfer_up,
max(iif(direction = 'DOWN', time_transfer, NULL)) as time_transfer_down,
datediff("minute",
max(iif(direction = 'UP', time_transfer, NULL))
max(iif(direction = 'DOWN', time_transfer, NULL))
) as minutes_diff
from tblPersonnel
group by Name_Personnel, VesselName, SailoutDate;

Thanks,
Both answers worked fine, although I saw different output, as not all data was completely correctly filled.
My final query became this.
SELECT DateDiff("n",Max(IIf([direction]='UP',[time_transfer],Null)),Max(IIf([direction]='DOWN',[time_transfer],Null))) AS minutes_diff, tblPersons.Name_Personnel, tblPersons.VesselName, tblPersons.SailoutDate, tblPersons.Type, tblPersons.VesselName, Max(IIf([direction]='up',[time_transfer],Null)) AS Time_transfer_UP, Max(IIf([direction]='Down',[time_transfer],Null)) AS Time_tranfer_DOWN
FROM tblPersons, QRY_Numberofsailingdays
GROUP BY tblPersons.Name_Personnel, tblPersons.SailoutDate, tblPersons.Type, tblPersons.VesselName, tblPersons.VesselName
HAVING (((tblPersons.SailoutDate) Between [Forms]![FRM_Working_Time_Personnel]![TXT_startdate] And [Forms]![FRM_Working_Time_Personnel]![TXT_enddate]));

Related

history of changes to a column

Please, consider the following scenario.
There are 2 tables: Core and History. Core looks as follows
HWDateStart
HWDateEnd
HWQueueID
2022-05-29 10:00:00
2022-06-04 00:45:00
WIN-S671INNTGRE.P00-K0-01
2022-05-29 10:00:00
2022-06-04 00:45:00
WIN-S671INNTGRE.P00-K0-02
History looks as follows
cntDatetime
cntSerialNumber
cntQueueName
cntQueueID
2022-05-29 02:28:00
SN01-01
p00-0000-01
WIN-S671INNTGRE.P00-K0-01
2022-05-29 02:28:00
SN02-01
p00-0000-02
WIN-S671INNTGRE.P00-K0-02
2022-06-04 00:26:00
SN02-02
p00-0000-02
WIN-S671INNTGRE.P00-K0-02
2022-06-04 00:26:00
SN01-01
p00-0000-01
WIN-S671INNTGRE.P00-K0-01
History holds a list of cntSerialNumber changes through the time
The following script that gives the user SerialNumber as it was at the beginning and the end of a certain period
SELECT Convert(date,[HWDateStart])
,Convert(date,[HWDateEnd])
,[HWQueueID]
, HS.cntSerialNumber
, HE.cntSerialNumber
FROM [watchdocstats].[dbo].[tblJT] SNTarget,
[watchdocstats].[dbo].[tblQueueByConfig] HS,
[watchdocstats].[dbo].[tblQueueByConfig] HE
WHERE
SNTarget.HWQueueID = HS.cntQueueID
AND SNTarget.HWQueueID = HE.cntQueueID
AND Convert(date,SNTarget.HWDateStart) = Convert(date,HS.cntDatetime)
AND Convert(date,SNTarget.HWDateEnd) = Convert(date,HE.cntDatetime)
But what if SerialNumber has been changed more than once down the road
Is there a way to select a table that would show commaseparated SerialNumbers in cntSerialNumber column?
Smth, like
(Start)
(End)
HWQueueID
cntSNHist
2022-05-29
2022-06-04
WIN-S671INNTGRE.P00-K0-01
SN01-01
2022-05-29
2022-06-04
WIN-S671INNTGRE.P00-K0-02
SN02-01,SN02-02,SN02-03
Depending on your DBMS, you should be able to use the LISTAGG function along with a GROUP BY clause

I'm looking to find an average difference between a series of 2 rows same column in SQL

So I've looked through a lot of questions about subtraction and all that for SQL but haven't found the exact same use.
I'm using a single table and trying to find an average response time between two people talking on my site. Here's the data sample:
id created_at conversation_id sender_id receiver_id
307165 2017-05-03 20:03:27 96557 24 1755
307166 2017-05-03 20:04:22 96557 1755 24
303130 2017-04-20 18:03:53 102458 2518 4475
302671 2017-04-18 20:11:20 102505 3100 1079
302670 2017-04-18 20:09:38 103014 3100 2676
350570 2017-09-18 20:59:56 103496 5453 929
290458 2017-02-16 13:38:47 103575 2841 2282
300001 2017-04-08 16:42:16 104159 2740 1689
304204 2017-04-24 17:31:25 104531 5963 1118
284873 2017-01-12 22:33:19 104712 3657 3967
284872 2017-01-12 22:31:38 104712 3967 3657
What I want is to find an Average Response Time based on the conversation_id
Hmmm . . . You can get the "response" for a given row by getting the next row between the two conversers. The rest is getting the average -- which is database dependent.
Something like this:
select avg(next_created_at - created_at) -- exact syntax depends on the database
from (select m.*,
(select min(m2.created_at)
from messages m2
where m2.sender_id = m.receiver_id and m.sender_id = m2.receiver_id and
m2.conversation_id = m.conversation_id and
m2.created_at > m.created_at
) next_created_at
from messages m
) mm
where next_created_at is not null;
A CTE will take care of bringing the conversation start and end into the same row.
Then use DATEDIFF to compute the response time, and average it.
Assumes there are only ever two entries per conversation (ignores others with 1 or more than 2).
WITH X AS (
SELECT conversation_id, MIN(created_at) AS convstart, MAX(created_at) AS convend
FROM theTable
GROUP BY conversation_id
HAVING COUNT(*) = 2
)
SELECT AVG(DATEDIFF(second,convstart,convend)) AS AvgResponse
FROM X

Create column based on grouping other values

I have difficulties formulating my issue.
I have a view which brings these results. There's a need to add a column to the view, which will pair up round-trip flights with identical number.
Flt_No From_Airport To_Airport Dep_Date RequiredResult
124 |LCA |CDG |10/19/14 5:00 1
125 |CDG |LCA |10/19/14 10:00 1
197 |LCA |BCN |10/4/12 5:00 2
198 |BCN |LCA |10/4/12 11:00 2
501 |LCA |HER |15/8/12 12:05 3
502 |HER |LCA |15/8/12 15:15 3
I.e. flight 124 is going from Larnaca to CDG, and flight 125 is going back from CDG to Larnaca - they both have to have the same identifier.
Round-trip flights will always have following flight numbers.
I have a bunch of conditions which I won't write now.
Omitting hours is not an option, they're important.
I was thinking dense_rank() but I don't know how to create one identifier for 2 flights with different numbers, please help.
If your data is similar to the sample data posted, then the following query should give the required result:
SELECT *,
DENSE_RANK() OVER (ORDER BY CASE
WHEN From_Airport < To_Airport THEN From_Airport
ELSE To_Airport
END)
FROM mytable
Join conditions are not limited to simple equality. Assuming {Flight No, Departure, Destination} is unique on any one day, then a self join should do it:
select whatever
from flights outbound
inner join flights inbound on outbound.flt_no+1 = inbound.flt_no
and cast(outbound.dep_date, date)
= cast(inbound.dep_date, date)
and outbound.From_Airport = inbound.To_Airport
and outbound.To_Airpott = inbound.From_Ariport

How to write a SQL query for showing route information from a flight database?

I have a set of flight data and I am trying to write a query (ex: recursive query using CTE) to show the No. of flights per routes, destination city, departure city, airline info, total time of delay per routes.
Currently I don't know a way to group total number of flights per route for each airline. I also have trouble grouping totaltimedelay for each airline's routes.
Sample flight data info - Four columns total (All the data below are from the fact table in OLAP database)
AirlineName DepartureCity DestinationCity TimeDelay(min) FlightID
CA NY CA 9 389
OA NJ TX 8 321
AA SEA NY 10 231
UA NY CA 20 098
HA NJ TX 15 321
OA NJ TX 20 123
< Expected output: 5 columns >
AirlineName DeparCity DestiCity TotalNumberofFlights TotaltimeDelay
Thanks a lot I hope I made it clear enough. Any sort of help or direction would be appreciated.
A simple GROUP BY should be enough...
SELECT
AirlineName,
DepartureCity AS DeparCity,
DestinationCity AS DestiCity,
COUNT(*) AS TotalNumberofFlights,
SUM(TimeDelay) AS TotaltimeDelay
FROM Flight
GROUP BY
AirlineName,
DepartureCity,
DestinationCity
Click here to see it in action & have a play in SqlFiddle.com

SQL hourly log , show all matching rows that have a value below threshold for n hours

I have a simple SQL log table (named market_history in SQLite) for US markets it looks something like this:
Sample table (market_history)
id datetime market percent
1 9/5/2014 7:50 ARIZONA 50.0
2 9/5/2014 7:50 ATLANTA 97.4
3 9/5/2014 7:50 AUSTIN 78.8
4 9/5/2014 7:50 BOSTON 90.9
6 9/5/2014 7:50 CHARLOTTE 100.0
7 9/5/2014 7:50 CHICAGO 90.3
This table is an hourly snapshot of network capacity in various systems in each market. What I would like to do is set up an alert system that if any one particular market is below a threshold percent (say 50) for more than 2 consecutive hours (each row is recorded every hour), it triggers an alert email.. So the query should show me a a unique list of Market names where the percents is < 50.0 for more than the last 2 consecutive entries
Here's the SQL I'm trying, but it's not working:
Sample SQL (not working):
SELECT
mh.datetime, mh.market, mh.percent
FROM markets_history mh
WHERE
(SELECT mh1.precent FROM markets_history mh1 WHERE mh1.datetime BETWEEN "2015-03-23 00:00:00" AND "2015-03-23 00:59:59" AND mh.market=mh1.market ) < 50 AND (SELECT mh2.precent FROM markets_history mh2 WHERE mh2.datetime BETWEEN "2015-03-23 01:00:00" AND "2015-03-23 01:59:59" AND mh.market=mh2.market ) < 50
ORDER by mh.datetime
I know I'm missing something.. any sugggestions
If the time windows are fixed and reliable, just make sure the largest one isn't more than the threshold. It wouldn't really matter how far back you look either if you needed to extend this to more than two.
select market
from markets_history mh
where mh.datetime between <last_two_hours> and <now>
group by mh.market
having max(percent) < 50.0
-- and count(*) = 2 /* if you need to be sure of two ... */
Here is an approach that should work in SQLite. Find the last good id (if any) in each market. Then count the number of rows larger than than id.
select lastgood.market,
sum(case when lastgood.market is null then 1
when lastgood.id < mh.id then 1
else 0
end) as NumInRow
from market_history mh left join
(select market, max(id) as maxid
from market_history mh
where percent < 50.0
group by market
) as lastgood
on lastgood.market = mh.market and lastgood.id < mh.id;
This query is a little bit complicated because it needs to take into account the possibility of there not being any good id. If that is the case, then all rows for the market count.