将排列转换为行组合的左连接条件

发布于 2024-10-04 02:14:21 字数 1022 浏览 1 评论 0原文

我有一个计划表,例如,

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

    t2.id

  • sort(array[t1.id,t2.id]) AS ids ... GROUP BY ids

I have a table of plans e.g.

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

I am generating the permutation of rows by left joining the table on itself (any number of times).

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 ...

How can I generate all the different combinations that provide service_1 and service_2 whilst avoiding duplication. The joining row cannot contain the same service e.g.

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

I am struggling with the join conditions for this approach. Also, is this fundamentally the wrong approach for solving this problem?

Possible ways I am trying to avoid duplication are:

  • ordered sets (I am yet to get this working) e.g. t1.id < t2.id

  • sort(array[t1.id,t2.id]) AS ids ... GROUP BY ids

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

临走之时 2024-10-11 02:14:21

此外,这从根本上来说是错误的吗?
解决这个问题的方法是什么?

我想是的。这看起来类似于集合打包问题和/或设置覆盖问题

我认为通过单个查询来完成此操作是不可行的(或者甚至可能)。您需要与要覆盖的服务一样多的联接,并且许多 WHERE 条件是该数量的函数。

我认为一种简单的、暴力的方法和简单的修剪在这里可能会起作用,因为无论如何你想要的是所有可能组合的列表。或者您可以预先计算所有有效组合并将它们存储在一个大表中。

无论你做什么,这对我来说至少是 O(rowscols) 。

Also, is this fundamentally the wrong
approach for solving this problem?

I think so. This looks similar to the set packing problem and/or the set cover problem.

I don't think it would be feasible (or maybe even possible) to do this with a single query. You need as many joins as there are services to be covered, and a number of WHERE conditions a function of that number.

I think a naïve, brute-force approach with simple pruning may work here, since what you want is a list of all the possible combinations anyway. Or you could pre-compute all the valid combinations and store them in a large table.

Whatever you do, this looks like at least O(rowscols) work to me.

感受沵的脚步 2024-10-11 02:14:21

假设您的 id 是 1,2,3 4. SELECT * FROMplans A INNER JOINplans 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 套组合。

Say you have the id's 1,2,3 4. SELECT * FROM plans A INNER JOIN plans B ON B.Id >= A.id will give you the following sets:

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

Which I believe is what you want - you have all 2 set combinations on the plans.

故人如初 2024-10-11 02:14:21

我认为我们没有足够的表结构/样本输入/样本输出。以下似乎回答了我们正在处理的有限情况的问题:

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),但总的来说,我们要求没有间隙。

抱歉,如果这看起来很散漫,或者不符合要求。如果您可以在您的问题中添加更多示例以及实际的表格结构,我也许可以做得更好。

I don't think we have enough table structure/sample input/sample output. The following appears to answer the question for the limited case we're dealing with:

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)

Basically, we only satisfy the join where there is a "gap" on one side or the other (service_x = 0), but we require, overall, that there are no gaps.

Sorry if this seems rambling, or doesn't fit the bill. If you could add more samples to your question, and the actual table structure, I may be able to do better.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文