在两个相关列上排序表

时间:2018-03-01 07:49:39

标签: sql oracle

我有一个像这样的映射表

+------+----+
| From | To |
+------+----+
|   14 | 40 |
|   40 | 32 |
|   32 | 95 |
|   88 | 56 |
|   47 | 88 |
|   60 | 32 |
+------+----+

该表存储将相互映射的节点ID。

因此,从上表中,前14个将被映射到40然后一些40和60的表达式将被映射到32,最后32个将被映射到95.

我想按照这样的映射顺序对此表进行排序

+------+----+-------+-------+
| From | To | Order | Group |
+------+----+-------+-------+
|   14 | 40 |     1 |     1 |
|   40 | 32 |     2 |     1 |
|   60 | 32 |     2 |     1 |
|   32 | 95 |     3 |     1 |
|   47 | 88 |     1 |     2 |
|   88 | 56 |     2 |     2 |
+------+----+-------+-------+

在此结果集中,顺序告诉使用映射的顺序。如果两行具有相同的顺序和组,则意味着两个from的表达式将映射到to。虽然group将单个映射链组合在一起。

有没有办法使用SQL查询以这种方式对表进行排序?

3 个答案:

答案 0 :(得分:1)

你已经将你的请求扩展到多个链,根据你的解释,你来自最后并寻找所有前辈(因此得到60-32记录,因为你来自32-95)。

使用多个链时,您还需要一个组密钥:

class Program
{
    [DllImport("user32.dll")]
    static extern bool SetCursorPos(int X, int Y);

    static Random rnd = new Random();

    static void Main(string[] args)
    {

        Rectangle screenRes = Screen.PrimaryScreen.Bounds;
        int widtMax = screenRes.Width;
        int heighMax = screenRes.Height;

        int w;
        int h;

        do
        {
            while (!Console.KeyAvailable)
            {
                w = rnd.Next(1, widtMax);
                h = rnd.Next(1, heighMax);

                SetCursorPos(w, h);
                System.Threading.Thread.Sleep(1000);
            }
        } while (Console.ReadKey(true).Key != ConsoleKey.Escape);
    }
}

Rextester演示:http://rextester.com/AIAYA93175

答案 1 :(得分:0)

您可以利用递归函数。

查看Recursive queries

 create table tbl (ffrom int, tto int);
insert into tbl values (40, 32);
insert into tbl values (32, 95);
insert into tbl values (14, 40);
select *
from   tbl
start with ffrom = 14
connect by ffrom = prior tto
FFROM | TTO
----: | --:
   14 |  40
   40 |  32
   32 |  95

dbfiddle here

select *
from   tbl
start with ffrom = (select min(ffrom) from tbl)
connect by ffrom = prior tto

答案 2 :(得分:0)

您需要递归查询。首先获取“To”中未出现“From”的所有记录,然后转到以下记录,依此类推。每一步都可以增加排序键。

with cte (fromid, toid, sortkey) as
(
  select fromid, toid, 1 as sortkey
  from mytable
  where fromid not in (select toid from mytable)
  union all
  select m.fromid, m.toid, cte.sortkey + 1
  from mytable m
  join cte on cte.toid = m.fromid
)
select fromid, toid
from cte
order by sortkey;