查询不重复三个表

时间:2014-07-03 07:19:19

标签: sql database oracle

我有一个带有三个表的oracle数据库。第一个表有ID, X, Y个点,第二个表有关于行的信息。第三个表在点(第一个表)和行(第二个表)之间有连接。

这是一个小例子

第一张桌子(POINTS):

ID_POINT        X       Y
1               -5      40.21
2               -3      41.23
3              -4.12    41.56
4             -7.34     42.68

第二个表(LINES):

ID_LINE     NAME
100         LINE1
200         LINE2

第三个表连接第二个表的LINES和第一个表的两个点(CONNECTIONS)

ID      FROM    TO
1         1     100
2       100     2
3        2      100 
4       100     1

FROMTO来自第一张和第二张表ID秒。您可以在此示例中看到POINT 1连接到LINE 100而LINE 100连接到POINT 2,因此在结束时LINE 100将POINT 1连接到POINT 2。 您还可以按相反顺序查看连接:POINT 2与LINE 200和LINE 100与POINT 1。

我需要在oracle中生成一个Query,它返回一个包含所有LINES及其坐标而不重复的表(因此本例中的LINE 100应该是一次而不是两次,因为我不需要知道相反的顺序)。对于此示例,此表应为:

ID_LINE     X       Y       X1      Y2
100         -5      40.21   -3      41.23

此示例仅显示LINE 100,但会有更多行。

我正在使用此查询,但我没有让它正常工作。有什么想法吗?

SELECT * FROM
    (
        SELECT LN.ID_LINE, 
               P1.X X,
               P1.Y Y,
               P2.X X,
               P2.Y Y,
               ROW_NUMBER() OVER(PARTITION BY ID_LINE ORDER BY SRC1.FROM) ORDER
       FROM
            (
              SELECT *
              FROM LINES
            ) LN,
            CONNECTIONS SRC1,
            CONNECTIONS SRC2,
            POINTS P1,
            POINTS P1
        WHERE SRC1.TO(+)=LN.ID_LINE AND
              SRC2.FROM(+)=LN.ID_LINE AND
              P1.ID_POINT(+)=SRC1.FROM AND
              P2.ID_POINT(+)=SRC2.TO
    )
    WHERE ORDER=1

2 个答案:

答案 0 :(得分:1)

首先我要提一下,这是一个非常错误的数据库设计。假设第100行连接点100和200.然后你会得到这些连接:

ID      FROM    TO
1       100     100
2       100     200
3       200     100 
4       100     100

你知道,从技术上讲,你不能看到第三张桌子中的一个点和一行是什么。而且:一个点导致一条线导致一个点???没有!一行以点开始结束。所以不应该只有两张表,而应该只有两张;点表和线表如下:

ID_LINE     NAME   FROM_ID_POINT  TO_ID_POINT
100         LINE1  1              2
200         LINE2  3              4

另一点是你不应该使用像FROM这样的关键字作为列名。

然而,即使给出了糟糕的设计,问题也应该是可以解决的。假设一个ID总是只能 一个点一行。所以我们必须先了解一下,一点是什么,一行是什么。因此,我们找到了所有点的所有线。然后我们按行分组找到两个相关的点(最小点和最大点相关;应该只有这两个)。然后使用点表连接以获得x和y。

select line.id_line, p1.x as x1, p1.y as y1, p2.x as x2, p2.y as y2
from
(
  select x.id_line, min(x.id_point) as id_start_point, max(x.id_point) as id_end_point
  from
  (
    select
      case when l.id is null then c.to else c.from end as id_line,
      case when l.id is null then c.from else c.to end as id_point
    from connections c
    left outer join lines l on l.id = c.from
  ) x
  group by x.id_line
) line
join points p1 on p1.id_point = line.id_start_point
join points p2 on p2.id_point = line.id_end_point;

答案 1 :(得分:0)

我认为这个查询只会显示每一行。诀窍是始终在case语句中按顺序选择from和to id,以便将连接(id,p1,p2)和(id,p2,p1)视为相同的连接。 / p>

SELECT
    L.ID_LINE,
    L.NAME
    P1.X1,
    P1.Y1,
    P2.X1,
    P2.Y2
FROM    
    LINES L
    JOIN (
      SELECT DISTINCT
        L.ID_LINE,
        CASE(WHEN C1.TO > C2.FROM THEN C1.TO ELSE C2.FROM END) FROM_ID,
        CASE(WHEN C1.TO < C2.FROM THEN C1.TO ELSE c2.FROM END) TO_ID
      FROM
        LINES L
        JOIN CONNECTIONS C1 ON C1.FROM = L.ID_LINE
        JOIN CONNECTIONS C2 ON C2.TO = L.ID_LINE
   ) t1 ON t1.LINE_ID = L.LINE_ID
   JOIN POINTS P1 ON P1.ID_POINT = t1.FROM_ID 
   JOIN POINTS P2 ON P2.ID_POINT = t1.TO_ID