Условия левого соединения для преобразования перестановки в комбинацию строк - PullRequest
4 голосов
/ 23 ноября 2010

У меня есть таблица планов, например,

id | service_1 | service_2 | ...
---------------------------------
1  |   true    |  true     | ...
2  |   true    |  false    | ...
3  |   false   |  true     | ...

Я генерирую перестановку строк, присоединяясь к таблице слева ( любое количество раз ).

SELECT t1.id, t2.id, t3.id
FROM plans AS t1 
LEFT JOIN plans AS t2
  ON t1.id != t2.id
  AND ...
LEFT JOIN plans AS t3
  ON t1.id != t2.id AND t2.id != t3.id AND t3.id != t1.id
  AND ...

Как мне сгенерировать все различные комбинации, которые предоставляют service_1 и service_2, избегая при этом дублирования. Строка соединения не может содержать один и тот же сервис. Например,

id | service_1 | service_2 | id | service_1 | service_2 |
---------------------------------------------------------
1  |   true    |  true     |NULL|    NULL   |    NULL   |
2  |   true    |  false    | 3  |    false  |    true   |

Я борюсь с условиями соединения для этого подхода.Кроме того, является ли это в корне неправильным подходом к решению этой проблемы?

Возможные способы, которыми я пытаюсь избежать дублирования:

  • упорядоченные множества (я пока не получилработает) например, t1.id

  • sort (array [t1.id, t2.id]) AS идентификаторы ... GROUP BY идентификаторы

Ответы [ 3 ]

2 голосов
/ 23 ноября 2010

Кроме того, это в корне неверный подход к решению этой проблемы?

Я так думаю.Это похоже на проблему упаковки набора и / или проблему покрытия набора .

Я не думаю, что это было бы осуществимо (или возможно даже возможно)сделать это с помощью одного запроса.Вам нужно столько объединений, сколько нужно покрыть услуг, и число WHERE определяет функцию от этого числа.

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

Что бы вы ни делали, это выглядит как минимум O (строки cols ) для меня.

1 голос
/ 23 ноября 2010

Скажем, у вас есть идентификатор 1,2,3 4. SELECT * FROM plans A INNER JOIN plans B ON B.Id >= A.id даст вам следующие наборы:

1,1
1,2
1,3
1,4
2,2
2,3
2,4
3,3
3,4
4,4

То, что я считаю, то, что вы хотите - у вас есть все 2 комбинации комбинаций в планах.

0 голосов
/ 23 ноября 2010

Я не думаю, что у нас достаточно структуры таблицы / выборки ввода / вывода выборки. Следующее, кажется, отвечает на вопрос для ограниченного случая, с которым мы имеем дело:

SELECT
    * /* TODO: Proper column list */
FROM
    plans t1
        left join
    plans t2
        on /* since SQL doesn't have a boolean, are the service columns bit? */
            (t1.service_1 = 0 or t2.service_1 = 0) and
            (t1.service_2 = 0 or t2.service_2 = 0)
WHERE
    (t1.service_1 = 1 or t2.service_1 = 1) and
    (t1.service_2 = 1 or t2.service_1 = 1)

По сути, мы удовлетворяем объединению только в тех случаях, когда имеется «разрыв» с одной или другой стороны (service_x = 0), но в целом мы требуем, чтобы разрывов не было.

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

...