taediumの日記

2010-12-24

[][][] F#、C#SQLで直積

Seq.collectやSelectManyが理解しづらいので簡単なコードで整理してみました。

F#

[<Test>]
let ``cartesian product`` () =
  let numbers = seq {for i in 1 .. 3 -> i}
  let results = 
    numbers 
    |> Seq.collect (fun n1 -> numbers |> Seq.map (fun n2 -> n1, n2)) 
  results
  |> Seq.iter (printfn "%A")

C#

[TestMethod]
public void TestCartesianProduct()
{
    var numbers = Enumerable.Range(1, 3);
    var results = numbers
        .SelectMany(n1 => numbers.Select(n2 => Tuple.Create(n1, n2)));
    results
        .ToList()
        .ForEach(Console.WriteLine);
}

C# (LINQ)

[TestMethod]
public void TestCartesianProduct_Linq()
{
    var numbers = Enumerable.Range(1, 3);
    var results =
        from n1 in numbers
        from n2 in numbers
        select Tuple.Create(n1, n2);
    results
        .ToList()
        .ForEach(Console.WriteLine);
}

SQL

SQL Server 2008を使っています。再帰クエリでつくった連番をテーブル型の変数に格納し、それから結合しています。

declare @numbers table (n int);
with x (id) as 
(
    select 1
    union all
    select id + 1 from x where id + 1 <= 3
)
insert into @numbers select * from x;

select a.n n1, b.n n2 from @numbers a, @numbers b

出力結果

出力結果はいずれも1,2,3の集合の直積になります。

n1n2
11
12
13
21
22
23
31
32
33

2009-02-03

[][]左辺に複数の式を指定する場合のIN演算子

create table foo(a int, b int);
select * from foo where (a, b) in ((1,1),(2,2));

OraclePostgreSQLMySQLでは使える。

SQL ServerDB2では使えない。