I have the below table format and wanted to compute the last column based on other two columns:
BASE_VERSION JOURNEY_NO LINE_NO DIRECTION OP_DEP_NO SEQ_NO BLOCK_NO DEP_TIME TRAV_TIME ARRV_TIME
20,160,603 33,263 176 1 2 1 21,760,010 5:25:00 ? 5:25:00
20,160,603 33,263 176 1 2 2 21,760,010 5:25:00 0:00:45 5:25:45
20,160,603 33,263 176 1 2 3 21,760,010 5:25:00 0:00:43 5:26:28
20,160,603 33,263 176 1 2 4 21,760,010 5:25:00 0:00:47 5:27:15
20,160,603 33,263 176 1 2 5 21,760,010 5:25:00 0:00:59 5:28:14
20,160,603 33,263 176 1 2 6 21,760,010 5:25:00 0:01:31 5:29:45
20,160,603 33,263 176 1 2 7 21,760,010 5:25:00 0:01:08 5:30:53
20,160,603 33,263 176 1 2 8 21,760,010 5:25:00 0:01:37 5:32:30
20,160,603 33,263 176 1 2 9 21,760,010 5:25:00 0:00:48 5:33:18
20,160,603 33,263 176 1 2 10 21,760,010 5:25:00 0:01:02 5:34:20
20,160,603 33,263 176 1 2 11 21,760,010 5:25:00 0:00:38 5:34:58
20,160,603 33,263 176 1 2 12 21,760,010 5:25:00 0:01:18 5:36:16
20,160,603 33,263 176 1 2 13 21,760,010 5:25:00 0:00:58 5:37:14
20,160,603 33,263 176 1 2 14 21,760,010 5:25:00 0:00:47 5:38:01
Last Column ARRV_TIME for first row is (DEP_TIME + TRAV_TIME) . from second row ARRV_TIME is calculated as prev value + current row TRAV_TIME.
eg: 1 row for ARRV_TIME is (5:25:00 +?) = 5:25:00. from 2 row to rest is calculated as prev result which is 5:25:00 + 0:00:45 = 5:25:45 then next row is 5:25:45 + 0:00:43 = 5:26:28 and so on for each LINE_NO and DIRECTION.
You describe a Cumulative Sum, one of the basic tasks for an Analytic Function:
SUM(column TRAV_TIME is based on)
OVER (PARTITION BY LINE_NO, DIRECTION
ORDER BY SEQ_NO
ROWS UNBOUNDED PRECEDING)
Add this to the column DEP_TIME is based on and then apply the interval calculation
result * INTERVAL '00:00:01' HOUR TO SECOND
This results in an Interval, if you need a Time datatype:
TIME '00:00:00' + (result * INTERVAL '00:00:01' HOUR TO SECOND)
Related
Could you help me how to write a query for the following issue:
There are two tables:
Table persons:
P_id Name BirthDate
1 N1 2016-08-02
2 N2 2015-05-02
3 N3 2013-06-01
4 N4 2014-01-09
Table visited:(p_id is foreign key to table persons)
Id. Visitor_id. P_id. Visit_date
1 10 1 2017-03-05
2 11 2 2017-01-01
3 10 2 2017-02-03
4 12 3 2016-05-07
5 11 4 2016-04-09
6 10 1 2017-04-09
We are going to get the count of visited by each Visitor and also count of visited distinct person on filter on for those person who their age are under 1, between 1 and 2, between 2 and 3 at date of visit_date by each visitor_id.
The results should be like :
Under_one Bet_one_two Bet_two_three
Visitor_id VisitedCount/PersonCount VisitedCount/PersonCount VisitedCount/PersonCount
10 2 1 1 1 0 0
11 0 0 1 1 1 1
12 0 0 0 0 1 1
Between 1 and 2 means the result of subtracting visited_date and birthdate (for example : the result of 2013/03/05 - 2011/06/07) is between 1 and 2 years.
I don't know if I can give you the output laid out exactly as you have specified, but this
SELECT
visited.Visitor_id,
visited.P_id,
Int(([Visit_date]-[BirthDate])/365) AS Age,
Count(persons.P_id) AS NumVisits
FROM persons INNER JOIN visited ON persons.P_id = visited.P_id
GROUP BY
visited.Visitor_id,
visited.P_id,
Int((-[BirthDate]+[Visit_date])/365);
returns
Visitor_id P_id Age NumVisits
10 1 0 2
10 2 1 1
11 2 1 1
11 4 2 1
12 3 2 1
I have got 2 tables. Example Table 1:
ID episode_id episode_start episode_end
----------------------------------------------------
1 1 1 2
1 2 4 5
1 3 96 105
1 4 110 114
2 1 1 4
2 2 13 24
Example Table 2
ID timestamp Other_info
--------------------------------
1 1 111
1 2 142
1 3 114
1 4 112
1 5 116
1 6 123
2 1 145
2 2 156
2 3 154
I would like to merge the two tables based upon table2.timestamp = between table1.episode_start and table1.episode_end.
The final table should be a subset of table 2 with only the timestamprows where there is an episode.
Question: How to do this? What is the most computational efficient way?
EDIT: In reallity my tables are much longer.
So, for example, the episode_start of ID = 1 be the same as the episode start of ID=1200 in episode 12. So simply merging them does not work.
EDIT: EXPECTED OUTPUT:
ID timestamp Other_info
--------------------------------
1 1 111
1 2 142
1 4 112
1 5 116
2 1 145
2 2 156
2 3 154
and so on. The merge is basically some sort of filter of table 2 by table 1.
select table2.id, timestamp, other_info
from table1
left join table2 on table2.timestamp between table1.episode_start and table1.episode_end
where table2.id = table1.id
Output:
id timestamp Other_info
---------------------------------------
1 1 111
1 2 142
1 4 112
1 5 116
2 1 145
2 2 156
2 3 154
i would like to add a sequence nr from a set value.
is this output possible?
p_id date days OUTPUT(what i want)
3385 2012-02-02 556 0
3385 2012-02-03 1 1
3385 2012-09-24 234 0
3385 2012-09-25 1 1
3385 2013-11-12 413 0
3385 2013-11-13 1 1
3385 2013-11-14 1 2
3385 2013-11-15 1 3
3385 2014-09-09 298 0
3385 2014-09-10 1 1
3385 2014-09-11 1 2
3385 2015-11-11 426 0
3385 2015-11-12 1 1
3385 2015-11-13 1 2
3385 2015-11-14 1 3
3385 2015-11-15 1 4
3385 2015-11-16 1 5
3385 2015-11-17 1 6
3385 2015-11-18 1 7
3385 2015-11-19 1 8
3385 2015-11-20 1 9
The days column counts days from the row abow it.
if the days value is greater the 5 then start a new "0" and then a new sequence number.
Try this:
SELECT p_id, [date], days,
ROW_NUMBER() OVER (PARTITION BY p_id, grp
ORDER BY [date]) - 1 AS [OUTPUT]
FROM (
SELECT p_id, [date], days,
SUM(IIF(days > 5, 1, 0)) OVER (PARTITION BY p_id
ORDER BY [date]) AS grp
FROM mytable ) AS t
Explanation:
The inner query uses SUM() OVER() to produce the following output:
p_id date days grp
===============================
3385 2012-02-02 556 1
3385 2012-02-03 1 1
3385 2012-09-24 234 2
3385 2012-09-25 1 2
3385 2013-11-12 413 3
3385 2013-11-13 1 3
3385 2013-11-14 1 3
3385 2013-11-15 1 3
3385 2014-09-09 298 4
3385 2014-09-10 1 4
3385 2014-09-11 1 4
3385 2015-11-11 426 5
3385 2015-11-12 1 5
3385 2015-11-13 1 5
3385 2015-11-14 1 5
3385 2015-11-15 1 5
3385 2015-11-16 1 5
3385 2015-11-17 1 5
3385 2015-11-18 1 5
3385 2015-11-19 1 5
3385 2015-11-20 1 5
grp field is essentially the running total of 'greater than 5' occurrences. Using this field in an outer query we can easily produce the required enumeration with ROW_NUMBER window function.
With Sql Server 2014:
I have two tables - Events and Locations, that share a time column and I need to merge them into one table order by time. In the Events table there is an Event column that I need to place in all the Locations row following that event (time wise), here is an example:
Events:
time event
------------
09:00 2
09:10 3
10:15 1
10:17 2
10:30 3
Locations:
time X Y
-------------
09:01 1 3
09:02 2 3
09:05 4 1
09:09 6 4
09:10 7 8
09:11 8 8
09:12 9 7
10:17 1 2
10:19 5 4
10:20 4 3
10:25 5 4
10:28 3 5
Merged Table:
time X Y event
--------------------
09:00 0 0 2
09:01 1 3 2 <
09:02 2 3 2 <
09:05 4 1 2 <
09:09 6 4 2 <
09:10 0 0 3
09:10 7 8 3 <
09:11 8 8 3 <
09:12 9 7 3 <
10:15 0 0 1
10:17 0 0 2
10:17 1 2 2 <
10:19 5 4 2 <
10:20 4 3 2 <
10:25 5 4 2 <
10:28 3 5 2 <
10:30 0 0 3
The elements that mark with '<' are the inserted Events.
Any ideas and help on how to perform this task is welcome.
You can use UNION ALL and APPLY:
SQL Fiddle
SELECT
[Time], X = 0, Y = 0, [Event]
FROM [Events]
UNION ALL
SELECT l.*, x.Event
FROM Locations l
CROSS APPLY(
SELECT TOP 1 *
FROM [Events]
WHERE [Time] <= l.[Time]
ORDER BY [Time] DESC
)x
ORDER BY [Time]
When I run a SQL query on a single table and here is the data (this is just a sample, error column might be more than 10)
time total Error
00:16 6 10000(E)
00:20 4 10000(E)
00:46 2 10000(E)
01:01 2 10000(E)
01:40 2 10000(E)
02:07 2 10000(E)
02:52 1 10000(E)
04:27 2 10000(E)
04:29 6 10000(E)
04:32 4 10000(E)
04:49 2 10000(E)
04:50 2 10000(E)
06:18 2 10000(E)
09:04 1 10000(E)
10:57 4 10000(E)
10:58 4 10000(E)
00:36 1 9401(E)
00:37 1 9401(E)
00:57 1 9401(E)
00:58 1 9401(E)
01:32 1 9401(E)
01:33 1 9401(E)
02:36 2 9401(E)
03:05 1 9401(E)
03:06 1 9401(E)
09:53 2 9401(E)
12:11 2 9401(E)
12:12 4 9401(E)
12:41 1 9401(E)
I want to write a SQL query so that I want to get the above data like this
time 10000(E) 9401(E)
---------------------------
00:16 6 0
00:20 4 0
00:36 0 1
00:37 0 1
00:46 2 0
00:57 0 1
00:58 0 1
01:01 2 0
01:32 0 1
01:33 0 1
01:40 2 0
02:07 2 0
02:36 0 2
02:52 1 0
03:05 0 1
03:06 0 1
04:27 2 0
04:29 6 0
04:32 4 0
04:49 2 0
04:50 2 0
06:18 2 0
09:04 1 0
09:53 0 1
10:57 4 0
10:58 4 0
12:11 0 2
12:12 0 4
12:41 0 1
is this possible??
Does this meet your requirement?
select e.time
, e.[10000(E)]
, e.[9401(E)]
from (
select time
, SUM(case when Error LIKE N'10000(E)' then Total else NULL end) as [10000(E)]
, null as [9401(E)]
from MyTable
where Error LIKE N'10000(E)'
group by time
union
select time
, null as [10000(E)]
, SUM(case when Error LIKE N'9401' then Total else NULL end) as [9401(E)]
from MyTable
where Error LIKE N'9401(E)'
group by time
) e
order by e.time
If no, please tell me about the result so that I can bring the righteous corrections.
The SUM function only comes to group the number of occurences of a same error into one given time, which seems to be what you have in your table, actually. So, it shouldn't modify any data. On the other hand, if you had two different records of the same error by the same time, then they should be grouped by this time and the total of occurences of this error will be additioned.
For your given in- and output it could be as simple as this.
SELECT *
FROM (
SELECT time
, [10000(E)] = Total
, [9401(E)] = 0
FROM YourTable
WHERE Error = '10000(E)'
UNION ALL
SELECT time
, [10000(E)] = 0
, [9401(E)] = Total
FROM YourTable
WHERE Error = '9401(E)'
) q
ORDER BY
time