创建所有可能组合的列表

时间:2012-02-03 19:53:24

标签: sql database combinations

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

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

例如。有Mary,Alice,June,Cindy,Elizabeth,Betty,Jax

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

  • 玛丽,爱丽丝
  • 玛丽,六月
  • Mary Cindy
  • Mary,Jax
  • Mary,Alice,June
  • Mary,Alice,Cindy
  • 玛丽,爱丽丝,伊丽莎白 ...
  • Mary,Alice,Jax
  • Mary,June,Cindy
  • 玛丽,六月,伊丽莎白 ...
  • Mary,June,Jax
  • Mary,Cindy,Elizabeth
  • Mary,Cindy,Betty
  • Mary,Cindy,Jax ...
  • Mary,Alice,June,Cindy
  • Mary,Alice,June,Elizabeth
  • Mary,Alice,June,Betty ...
  • Mary,Alice,June,Cindy,Elizabeth
  • Mary,Alice,June,Cindy,Betty

任何人都知道在SQL,Access或C#中执行此操作的方法吗?如果那里有另一种我可以在DB上使用的语言,我会非常感激!

谢谢, 玛利亚

5 个答案:

答案 0 :(得分:3)

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

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=#

答案 1 :(得分: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

答案 2 :(得分:1)

如果您的意思是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());

答案 3 :(得分:0)

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

答案 4 :(得分:0)

有点尴尬,但会做的伎俩,或者为每个名称写一个带有嵌套循环的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;

这将生成笛卡尔积而不会复制任何名称!