Wednesday, June 27, 2012

Cross Join Queries and Non-equi Join Queries

using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace LinqStuff.Tests
{
   [TestClass]
   public class LinqTests
   {
      public LinqTests()
      {
      }
      
      [TestMethod]
      public void CrossJoinTest()
      {
         int[] numbers = {1, 2, 3, 4};
         string[] letters = {"a", "b", "c"};
         IEnumerable<string> query = from x in numbers
                              from y in letters
                              select x.ToString() + y;
         Assert.AreEqual(query.Count(), 12);
         Assert.AreEqual(query.ElementAt(0), "1a");
         Assert.AreEqual(query.ElementAt(1), "1b");
         Assert.AreEqual(query.ElementAt(2), "1c");
         Assert.AreEqual(query.ElementAt(3), "2a");
         Assert.AreEqual(query.ElementAt(4), "2b");
         Assert.AreEqual(query.ElementAt(5), "2c");
         Assert.AreEqual(query.ElementAt(6), "3a");
         Assert.AreEqual(query.ElementAt(7), "3b");
         Assert.AreEqual(query.ElementAt(8), "3c");
         Assert.AreEqual(query.ElementAt(9), "4a");
         Assert.AreEqual(query.ElementAt(10), "4b");
         Assert.AreEqual(query.ElementAt(11), "4c");
      }
      
      [TestMethod]
      public void NonEquiJoinTest()
      {
         string[] names = { "Tom", "Dick", "Harry" };
         IEnumerable<string> query = from x in names
                              from y in names
                              where x.CompareTo(y) < 0
                              select x + " vs " + y;
         Assert.AreEqual(query.Count(), 3);
         Assert.AreEqual(query.ElementAt(0), "Dick vs Tom");
         Assert.AreEqual(query.ElementAt(1), "Dick vs Harry");
         Assert.AreEqual(query.ElementAt(2), "Harry vs Tom");
      }
   }
}

 
 

The first query is a Cross Join. It returns one record for every possible combination across two flat collections, finding the same possibilities one might find in making a grid of results:

  a b c
1 1a 1b 1c
2 2a 2b 2c
3 3a 3b 3c
4 4a 4b 4c

...while returning a flat collection:

1a 1b 1c 2a 2b 2c 3a 3b 3c 4a 4b 4c

The second query is a Non-equi Join. If not for where x.CompareTo(y) < 0 it would do the same thing as a Cross Join. The where clause keeps an item from being matched to itself and ending up in a variation of an existing match. Pretty cool. This comes from page 384 of C# 4.0 in a Nutshell.

No comments:

Post a Comment