通过查询sql复杂组(oracle jpa)

时间:2015-10-22 20:53:15

标签: sql oracle jpa

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)

我有一个由段(1行= 1段)和路由(多段)组成的表。

路线由具有相同“let”和“dir”组合的段组成。所以前3行是一行,最后3行是另一行。

路线中的第一个分段是num最小的行。

  • 因此,行id = 0是路径1中的第一个分段
  • ,最后一行id = 5是路线2中的第一个分段。

我想根据该路线的第一段等于给定国家/地区返回构成路线的行。

如果我过滤了CA的“ctry”,结果如下:

id     let    num     dir   ctry
--------------------------------
3       B      25      E     US
4       B      30      E     CA
5       B      20      E     CA

3 个答案:

答案 0 :(得分:2)

 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

根据您的评论 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';

答案 1 :(得分:2)

在Oracle中,您可以使用分析功能执行此操作:

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更受限制。这可能有效:

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';

答案 2 :(得分:1)

http://sqlfiddle.com/#!9/ae58a/1

通过使用你们的方向,我想出了一个可读的好解决方案。谢谢juan和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';