Организация массива с как можно меньшим количеством смежных значений - PullRequest
3 голосов
/ 15 октября 2011

С таким массивом:

[google, google, yahoo, yahoo, yahoo, msn, msn, msn, google]

как лучше расположить его с как можно меньшим количеством смежных значений?Цель состоит в том, чтобы получить что-то вроде этого, например:

[google, msn, yahoo, google, yahoo, msn, yahoo, msn, google]

Еще лучше было бы алгоритм, который гарантирует, что любые подобные значения находятся как можно дальше друг от друга.

И дажеЛучше было бы сделать это напрямую в SQL.

Я делаю это для сценария, над которым я работаю, который отправляет информационные бюллетени, и я бы хотел избежать одновременной отправки слишком большого количества писем на один и тот же домен.

[править] Я использую MySQL

Ответы [ 2 ]

4 голосов
/ 15 октября 2011

Используя SQL Server 2005 и выше, вы можете воспользоваться функциональностью ROW_NUMBER

  • Добавить номер строки к каждому элементу, разделяя его по имени.
  • выбрать из этого подзапроса
  • упорядочить результаты по имени и имени.

Ваше требование о том, что они должны быть как можно дальше друг от друга, может быть не выполнено, но в целом этого будет достаточно.

Оператор SQL

SELECT  Site
FROM    (
            SELECT  Site, o = ROW_NUMBER() OVER (PARTITION BY Site ORDER BY Site)
            FROM    q
        ) q
ORDER BY                
        o, Site

Результаты

Google MSN Yahoo Yahoo Google MSN Yahoo MSN Yahoo

Тестовый скрипт

;WITH q ([site])AS (
    SELECT 'google'
    UNION ALL SELECT 'google'
    UNION ALL SELECT 'yahoo'
    UNION ALL SELECT 'yahoo'
    UNION ALL SELECT 'yahoo'
    UNION ALL SELECT 'msn'
    UNION ALL SELECT 'msn'
    UNION ALL SELECT 'msn'
    UNION ALL SELECT 'google'   
)
SELECT  Site
FROM    (
            SELECT  Site, o = ROW_NUMBER() OVER (PARTITION BY Site ORDER BY Site)
            FROM    q
        ) q
ORDER BY                
        o, Site
0 голосов
/ 25 октября 2011

Спасибо Ливен, я адаптировал ваш ответ к MySQL, и он отлично работает:

select *
from (
    select
      @i := if(@last_name != t2.name, 1, @i + 1) as row_number,
      @last_name := t2.name as `name`
    from
      site t2,
      (select @i := 0) vt1,
      (select @last_name := null) vt2
    order by t2.name
) t1
order by t1.row_number, t1.name
;

дает:

+------------+--------+
| row_number | name   |
+------------+--------+
|          1 | google |
|          1 | msn    |
|          1 | yahoo  |
|          2 | google |
|          2 | msn    |
|          2 | yahoo  |
|          3 | google |
|          3 | msn    |
|          3 | yahoo  |
+------------+--------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...