SQL以“循环”顺序返回行

时间:2009-07-21 17:53:14

标签: sql postgresql

我有一堆存储在表中的URL等待被脚本删除。但是,其中许多网址来自同一网站。我想以“网站友好”的顺序返回这些网址(也就是说,尝试连续避免来自同一网站的两个网址),这样我就不会在短时间内通过制作太多的http请求而意外阻止

数据库布局是这样的:

create table urls (
    site varchar,       -- holds e.g. www.example.com or stockoverflow.com
    url varchar unique
);

示例结果:

SELECT url FROM urls ORDER BY mysterious_round_robin_function(site);

http://www.example.com/some/file
http://stackoverflow.com/questions/ask
http://use.perl.org/
http://www.example.com/some/other/file
http://stackoverflow.com/tags

我想到了像“ORDER BY site <> @last_site DESC”这样的东西,但我不知道如何写这样的东西。

5 个答案:

答案 0 :(得分:4)

在我的博客中查看此文章,了解有关其工作原理的更详细说明:

使用新的PostgreSQL 8.4

SELECT  *
FROM    (
        SELECT  site, url, ROW_NUMBER() OVER (PARTITION BY site ORDER BY url) AS rn
        FROM    urls
        )
ORDER BY
        rn, site

使用旧版本:

SELECT  site,
        (
        SELECT  url
        FROM    urls ui
        WHERE   ui.site = sites.site
        ORDER BY
                url
        OFFSET  total
        LIMIT   1
        ) AS url
FROM    ( 
        SELECT  site, generate_series(0, cnt - 1) AS total
        FROM    (
                SELECT  site, COUNT(*) AS cnt
                FROM    urls
                GROUP BY
                        site
                ) s
        ) sites
ORDER BY
        total, site

,虽然效率可能较低。

答案 1 :(得分:3)

我认为你过于复杂了。为什么不使用

订购NewID()

答案 2 :(得分:2)

你要求循环赛,但我认为这很简单

SELECT site, url FROM urls ORDER BY RANDOM()

会做到这一点。即使来自同一站点的URL聚集在db中,它也应该工作。

答案 3 :(得分:0)

如果URL不经常更改,您可以提出一个稍微复杂的工作,您可以定期(夜间?)运行,这将根据存在的不同站点为每条记录分配整数。

您可以做的是编写一个从URL解析域的例程(您应该能够找到几乎可以在任何地方执行此操作的片段。)

然后,您创建一个包含每个唯一域的临时表,以及一个数字。

然后,对于URL表中的每个记录,您在临时表中查找域,为该记录分配存储在那里的号码,并在该临时表的号码中添加一个大号。

然后在剩下的时间里,按数字排序。


以下是您在问题中使用的五条记录的示例:

网址:

临时表:

example.com       1
stackoverflow.com 2
perl.org          3

然后,对于每个URL,您在临时表中查找值,并向其添加3(因为它有3个不同的记录):

迭代1:

网址:

http://www.example.com/some/file         1
http://www.example.com/some/other/file   NULL
https://stackoverflow.com/questions/ask   NULL
https://stackoverflow.com/tags            NULL
http://use.perl.org/                     NULL

临时表:

example.com       4
stackoverflow.com 2
perl.org          3

迭代2:

网址:

http://www.example.com/some/file         1
http://www.example.com/some/other/file   4
https://stackoverflow.com/questions/ask   NULL
https://stackoverflow.com/tags            NULL
http://use.perl.org/                     NULL

临时表:

example.com       7
stackoverflow.com 2
perl.org          3

等等,直到你到达

http://www.example.com/some/file         1
http://www.example.com/some/other/file   4
https://stackoverflow.com/questions/ask   2
https://stackoverflow.com/tags            5
http://use.perl.org/                     3

对于很多记录来说,它会很慢。并且很难使用许多插入/删除,但结果将是一个完美的循环排序。

答案 4 :(得分:0)

有一个更简单,更快速的解决方案......

  • 添加TEXT
  • 类型的sort_order列
  • 添加ON INSERT触发器,将sort_order设置为md5(url)
  • index_order上的索引
  • 抓取(sort_order,主键)订单中的行

- &GT;它非常快且索引 - &GT;行将以可重复但随机的顺序出现