id let num dir ctry
----------------------------------
0 A 10 W US <- first row of route (A-W)
1 A 20 W CA
2 A 30 W MX
3 B 25 E US
4 B 30 E CA
5 B 20 E CA <- first row of route (B-E)
I have a table which is composed of segments (1 row = 1 segment) and routes (multiple segments).
A route is composed of segments having the same "let" and "dir" combination. So the first 3 rows is one route, and the last 3 rows is another.
The first segment in the route is the row with the smallest num
.
id = 0
is the first segment in route 1, id = 5
is the first segment in route 2. I want to return the rows that make up a route based on the 1st segment of that route equaling a given country.
If I filtered on a "ctry" of CA the result would be the following:
id let num dir ctry
--------------------------------
3 B 25 E US
4 B 30 E CA
5 B 20 E CA
SELECT *
FROM YourTable
WHERE (let, dir) IN (SELECT distinct let, dir
FROM YourTable Y
WHERE Y.ctry = 'CA')
OR
SELECT L.*
FROM YourTable L
JOIN (SELECT distinct let, dir
FROM YourTable Y
WHERE Y.ctry = 'CA') R
ON L.let = R.let
AND L.dir = R.dir
Based on your comment SqlFiddleDemo
SELECT R.*
FROM
(SELECT let, dir, min(num) as minnum
FROM Routes t
GROUP BY let, dir
) minT
JOIN (SELECT t.*
FROM Routes t
) firstrow
ON minT.let = firstrow.let
AND minT.dir = firstrow.dir
AND minT.minnum = firstrow.num
JOIN Routes R
ON firstRow.let = R.let
AND firstRow.dir = R.dir
AND firstRow.Ctry = 'CA';
In Oracle, you can do this using analytics function:
select t.*
from (select t.*,
min(country) keep (dense_rank first order by num) over (partition by let, dir) as first_country
from t
) t
where first_country = 'CA';
JPA is more limited. This might work:
select t.*
from t join
(select let, dir, min(num) as minnum
from t
group by let, dir
) ld
on t.let = ld.let and t.dir = ld.dir join
t tt
on tt.let = ld.let and tt.dir = ld.dir and tt.num = ld.minnum
where tt.country = 'CA';
http://sqlfiddle.com/#!9/ae58a/1
By using your guys direction I came up with a good solution that is readable. Thanks juan and gordon.
SELECT Routes.* FROM Routes
JOIN (SELECT let,dir,min(num) as minnum
FROM Routes
GROUP BY let, dir
) ld JOIN Routes tt
ON tt.let = ld.let AND tt.dir = ld.dir AND tt.num = ld.minnum
AND Routes.let = ld.let AND Routes.dir = ld.dir
WHERE tt.ctry = 'CA';
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.