【问题标题】:Creating a list of all possible combinations创建所有可能组合的列表
【发布时间】:2012-02-03 19:53:23
【问题描述】:

我正在尝试执行以下操作。

我想创建特定事物之间所有可能关系的列表。

例如。有玛丽、爱丽丝、琼、辛迪、伊丽莎白、贝蒂、贾克斯

我想为这样的列表创建所有可能的组合:

  • 玛丽,爱丽丝
  • 玛丽,六月
  • 玛丽·辛迪
  • 玛丽,贾克斯
  • 玛丽,爱丽丝,六月
  • 玛丽、爱丽丝、辛迪
  • 玛丽、爱丽丝、伊丽莎白 ...
  • 玛丽、爱丽丝、贾克斯
  • 玛丽,六月,辛迪
  • 玛丽,六月,伊丽莎白 ...
  • 玛丽,六月,贾克斯
  • 玛丽、辛迪、伊丽莎白
  • 玛丽、辛迪、贝蒂
  • 玛丽、辛迪、贾克斯 ...
  • 玛丽、爱丽丝、琼、辛迪
  • 玛丽、爱丽丝、琼、伊丽莎白
  • 玛丽、爱丽丝、琼、贝蒂 ...
  • 玛丽、爱丽丝、琼、辛迪、伊丽莎白
  • 玛丽、爱丽丝、琼、辛迪、贝蒂

有人知道在 SQL、Access 或 C# 中执行此操作的方法吗?如果我可以在 DB 上使用另一种语言,我将不胜感激!

谢谢, 玛丽亚

【问题讨论】:

  • 所有可能的组合直到什么?一排二十? Mary, Mary 有效吗?为什么没有Mary, Elisabeth
  • 为什么没有Mary(只有1个名字)? Mary, AliceAlice, Mary 一样吗?
  • @Oded - Mary, Mary 在这种情况下无效。玛丽,伊丽莎白是有效的,我只是跳到玛丽,贾克斯的 2 对组合中的最后一个组合。
  • @Ypercube - 我正在寻找配对。在这种情况下,我想使用 Mary 是基础名称和后续名称作为名字的配对。
  • 请问什么 DBMS?我在 SQL Server 中有一个可以移植到其他 DBMS 的解决方案,但很高兴知道您在寻找什么。

标签: sql database combinations


【解决方案1】:

您可能喜欢许多现代数据库服务器为此使用的递归查询。

ACCESS 不是其中之一 :(

以下是postres的示例

postgres=# with RECURSIVE y1(b,c,d) as (
postgres(#      with x1(a) as (
postgres(#              values('a')
postgres(#              union all
postgres(#              values ('b')
postgres(#              union all
postgres(#              values ('c')
postgres(#              union all
postgres(#              values ('d')
postgres(#      )
postgres(#      select a,a,1
postgres(#      from x1
postgres(#      union all
postgres(#      select a||b,a,d+1
postgres(#      from x1
postgres(#              join y1 on (a < c)
postgres(# )
postgres-# select *
postgres-# from y1;
  b   | c | d
------+---+---
 a    | a | 1
 b    | b | 1
 c    | c | 1
 d    | d | 1
 ab   | a | 2
 ac   | a | 2
 ad   | a | 2
 bc   | b | 2
 bd   | b | 2
 cd   | c | 2
 abc  | a | 3
 abd  | a | 3
 acd  | a | 3
 bcd  | b | 3
 abcd | a | 4
(15 rows)


postgres=#

【讨论】:

  • 谢谢 Alessandro,我不熟悉 postgres,但我会进一步研究这个解决方案。
【解决方案2】:

SQL 可以非常适合这类事情。如果您想要非常广泛,它会变得很棘手,但如果您知道您想要最多五个项目的所有组合:

DECLARE @things TABLE (n nvarchar(50));

INSERT INTO @things (n) VALUES ('Mary'),('Alice'),('June'),('Cindy'),('Elizabeth'),('Betty'),('Jax'), (null);

SELECT 
  ISNULL(t1.n + ',', '') 
  + ISNULL(t2.n + ',', '') 
  + ISNULL(t3.n+ ',', '') 
  + ISNULL(t4.n+ ',', '') 
  + ISNULL(t5.n, '') 
FROM @things AS t1
JOIN @things AS t2 ON 1=1
JOIN @things AS t3 ON 1=1
JOIN @things AS t4 ON 1=1
JOIN @things AS t5 ON 1=1

【讨论】:

  • +1 尽管您确实对看起来像 Mary,Mary,Mary,Mary,Mary 的东西进行了一些清理,但实际上它应该只是 Mary。此外,您应该尝试在 FROM 子句中多次列出 @things 而没有 JOIN 条件。
  • @Yuck 关于清理是正确的。我只是想帮助玛丽亚开始。她可能还想去掉一些悬空的逗号。 FROM 子句中的多个项目在大多数情况下都可以使用,但我觉得这种风格令人困惑。
  • 你拥有的是FROM @things AS t1 CROSS JOIN @things AS t2 CROSS JOIN ...
  • JOIN 可能很有用,用于将 FROM 部分更改为:FROM @things AS t1 JOIN @things AS t2 ON t1.name &lt; t2.name ...
  • 现在尝试上面的方法,它给我一个特定逗号的 INSERT 语句的语法错误
【解决方案3】:

如果您的意思是 power set,那么您可以在 C# 中使用以下内容

public IEnumerable<IEnumerable<T>> GetPowerSet<T>(List<T> list)
{
    return from m in Enumerable.Range(0, 1 << list.Count)
           select
             from i in Enumerable.Range(0, list.Count)
             where (m & (1 << i)) != 0
             select list[i];
}

用法:

var names = new List<string> { "Mary", "Alice", "June", "Cindy", "Elizabeth", "Betty", "Jax" };
var powerSet = GetPowerSet(names);
foreach (var nameCollection in powerSet)
{
  foreach (var name in nameCollection)
  {
    Console.Write(name);
  }
  Console.WriteLine();
}

您可能希望删除少于 2 个名称的任何集合,以及完整的名称集:

var cleaned = powerSet.Where(nc => nc.Count() > 1 && nc.Count() < names.Count());

【讨论】:

  • 嗯,现在也试试这个,看看我能不能让它工作。谢谢devdigital。另外,我正在使用 VS 2008 上面的代码有什么不同吗?
  • 不应该没问题,你需要.NET framework 3.5或更高版本,你应该添加一个using System.Linq;声明到源代码的顶部,并确保您引用的是 System.Core 程序集。
【解决方案4】:

如果您有定义数量的元素,例如 Mary、Alice、June、Cindy、Elizabeth、Betty、Jax,在这种情况下为 8 个元素,您可以嵌套 8 个循环来显示元素的所有可能排列。如果数字未知,则需要递归函数。

【讨论】:

  • 感谢 whitelionV 到时候我会进一步研究递归函数。
【解决方案5】:

有点尴尬,但可以解决问题,或者为每个名称编写一个带有嵌套循环的 SQL proc。

为每个名字创建一个单独的表,例如:

CREATE TABLE MARY(name VARCHAR(30));
INSERT INTO  MARY VALUES ("Mary");

{do the same for each different name and then}

SELECT * 
  FROM mary, 
       alice,
       june,
       cindy,
       elizabeth,
       betty,
       jax;

这将生成一个笛卡尔积而不重复任何名称!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 2012-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多