Repository: jtablesaw/tablesaw (java)

Issue:
Joins don't work when one table has only one column
Hi guys!
I'm trying to do an inner join on simple tables:

```kotlin
        val table1 = Table.create(
            "table1",
            StringColumn.create("customer_id", arrayOf("1", "2", "3", "4", "5")),
            DoubleColumn.create("amount", arrayOf(1, 2, 3, 4, 5))
        )

        val table2 = Table.create(
            "table2",
            DoubleColumn.create("amount", arrayOf(1, 2, 3, 4, 5))
        )

        val joined = table1
            .join("amount")
            .inner(table2, "amount")

        log(table1.shape())
        log(table2.shape())
        log(joined.shape())
```
and here is result:
```
2018-09-06 17:17:39,117 [main] INFO  Script - 5 rows X 2 cols 
2018-09-06 17:17:39,117 [main] INFO  Script - 5 rows X 1 cols 
2018-09-06 17:17:39,117 [main] INFO  Script - 0 rows X 2 cols 
```
The table is empty. Am i doing it wrong?
I'm using v0.25.2

Pull request:
Fix Inner Join when one table has a single column
Thanks for contributing.

- [X] Tick to sign-off your agreement to the [Developer Certificate of Origin (DCO) 1.1](https://developercertificate.org)

## Description

Fix joins when one or both tables only contains join columns. Fixes #381 

## Testing

Added tests for 
* inner join where both tables contain single column
* inner join where only right table contains single column.
* inner join where both tables contain only join keys.
* outer join where right table contains single column.


Patch:
diff --git a/core/src/main/java/tech/tablesaw/joining/DataFrameJoiner.java b/core/src/main/java/tech/tablesaw/joining/DataFrameJoiner.java
index 2111c6c6..bf059ef9 100644
--- a/core/src/main/java/tech/tablesaw/joining/DataFrameJoiner.java
+++ b/core/src/main/java/tech/tablesaw/joining/DataFrameJoiner.java
@@ -276,11 +276,10 @@ public class DataFrameJoiner {
             }
 
             Table table2Rows = table2.where(rowBitMapMultiCol);
-            table2Rows.removeColumns(col2Names);
             if (outer && table2Rows.isEmpty()) {
                 withMissingLeftJoin(result, table1Rows);
             } else {
-                crossProduct(result, table1Rows, table2Rows);
+                crossProduct(result, table1Rows, table2Rows, col2Names);
             }
         }
         return result;
@@ -649,10 +648,13 @@ public class DataFrameJoiner {
     }
 
     @SuppressWarnings({"rawtypes", "unchecked"})
-    private void crossProduct(Table destination, Table table1, Table table2) {
+    private void crossProduct(Table destination, Table table1, Table table2, String[] col2Names) {
+        int table2RowCount = table2.rowCount();
+        // Remove join columns
+        table2.removeColumns(col2Names);
         for (int c = 0; c < table1.columnCount() + table2.columnCount(); c++) {
             for (int r1 = 0; r1 < table1.rowCount(); r1++) {
-                for (int r2 = 0; r2 < table2.rowCount(); r2++) {
+                for (int r2 = 0; r2 < table2RowCount; r2++) {
                     if (c < table1.columnCount()) {
                         Column t1Col = table1.column(c);
                         destination.column(c).append(t1Col, r1);


Test patch:
diff --git a/core/src/test/java/tech/tablesaw/joining/DataFrameJoinerTest.java b/core/src/test/java/tech/tablesaw/joining/DataFrameJoinerTest.java
index 88c2c799..50931899 100644
--- a/core/src/test/java/tech/tablesaw/joining/DataFrameJoinerTest.java
+++ b/core/src/test/java/tech/tablesaw/joining/DataFrameJoinerTest.java
@@ -488,6 +488,37 @@ public class DataFrameJoinerTest {
         assertEquals(5, joined.rowCount());
     }
 
+    @Test
+    public void innerJoinSingleColumn() {
+        Table joined = SP500.select("Date").joinOn("Date")
+            .inner(ONE_YEAR.select("Date"));
+        assertEquals(5, joined.rowCount());
+        assertEquals(1, joined.columnCount());
+    }
+
+    @Test
+    public void innerJoinSingleColumnOnRight() {
+        Table joined = SP500.joinOn("Date").inner(ONE_YEAR.select("Date"));
+        assertEquals(5, joined.rowCount());
+        assertEquals(2, joined.columnCount());
+    }
+
+    @Test
+    public void innerJoinMultipleColumnsAllColumnsInJoinKey() {
+        Table table1 = Table.create(
+            SP500.dateColumn("Date"),
+            SP500.dateColumn("Date").copy().setName("Date2")
+        );
+        Table table2 = Table.create(
+            ONE_YEAR.dateColumn("Date"),
+            ONE_YEAR.dateColumn("Date").copy().setName("Date2")
+        );
+
+        Table joined = table1.joinOn("Date", "Date2").inner(table2);
+        assertEquals(5, joined.rowCount());
+        assertEquals(2, joined.columnCount());
+    }
+
     @Test
     public void innerJoinWithBoolean() {
         Table joined = DUPLICATE_COL_NAME_DOGS.joinOn("Good")
@@ -573,6 +604,13 @@ public class DataFrameJoinerTest {
         assertEquals(2, joined.column("Feed").countMissing());
     }
 
+    @Test
+    public void fullOuterJoinColTwoOnlyJoinKeys() {
+        Table joined = ANIMAL_FEED.joinOn("Animal").fullOuter(ANIMAL_NAMES.select("Animal"));
+        assertEquals(2, joined.columnCount());
+        assertEquals(8, joined.rowCount());
+    }
+
     @Test
     public void fullOuterJoinNew() {
         Table joined = ANIMAL_FEED.joinOn("Animal").fullOuter(true, ANIMAL_NAMES);