通过三个数据表进行分页?

时间:2012-06-19 04:06:50

标签: sql sqlite

我有三个数据表:

table: cars    [10,000 rows]
table: planes  [2,000 rows]
table: trains  [50 rows]

我希望能够向用户显示从三个表中获取的数据页面,如:

car
plane
train
car
plane
train
...

关键是他们可以继续分页,查看每种类型之一,直到每个表都用完为止。例如,在某些时候,每个页面只包含汽车,因为飞机和火车表将在汽车表之前耗尽。

我是否可以运行查询以从每个表中获取一行,直到达到限制为止?类似的东西:

SELECT * FROM cars, planes, trains ORDER BY (natural row ordering?) LIMIT 20;

我能想到的唯一方法是创建一个主表,并在插入它们时为每一行分配一个虚拟整数:

  id |  type  | description | dummy_integer
--------------------------------------------
 ...    car     ...             0
 ...    plane   ...             1
 ...    train   ...             2
 ...    car     ...             3
 ...    plane   ...             4
 ...    train   ...             5
 ...    ...     ...             ...
 ...    car     ...             8000
 ...    car     ...             8001
 ...    car     ...             8002
 ...    ...     ...             ...

然后我可以做:

SELECT * FROM master_table ORDER BY dummy_integer ASC LIMIT 20;

并使用最后看到的dummy_integer完成分页:

SELECT * FROM master_table WHERE dummy_integer > 20 
    ORDER BY dummy_integer ASC LIMIT 20;

然后问题就变成了当我获得一些新的火车记录时,我可以将它们附加到master_table的末尾,但是它们的虚拟整数值会将它们一直放在最后。因此,如果用户从一开始就开始查看我的页面,他们将不会看到更新的列车数据,直到他们翻阅汽车沙漠,而不是与汽车/飞机向前交叉。

除了上述(不那么好)之外,还有什么好办法吗?

由于

2 个答案:

答案 0 :(得分:1)

查询中的逗号实际上是否实际执行了连接?

我使用UNIONORDER BY来实现这一目标:

SELECT id, type, description FROM cars
UNION
SELECT id, type, description FROM planes
UNION
SELECT id, type, description FROM trains
ORDER BY id, type

working example

对于分页,您可以将LIMITOFFSET一起使用(请参阅docs)。

答案 1 :(得分:0)

如果你使用的是oracle,这对你有用:

select
    1 as typer,
    a.id,
    a.type,
    a.description,
    row_number() over (partition by typer order by typer) as ranker
from
    cars a
union
select
    1 as typer,
    a.id,
    a.type,
    a.description,
    row_number() over (partition by typer order by typer) as ranker
from
    planes a
union
select
    1 as typer,
    a.id,
    a.type,
    a.description,
    row_number() over (partition by typer order by typer) as ranker
from
    trains a
order by
    ranker asc;

我没有更改你的列名,但你使用的是一些保留字,可能不是最好的。