diff --git a/src/JoiningTest.java b/src/JoiningTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9352630c3b1ca4b831112054a6ded532493d8c91
--- /dev/null
+++ b/src/JoiningTest.java
@@ -0,0 +1,116 @@
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
+import org.junit.Assert;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import javax.naming.spi.DirStateFactory.Result;
+import javax.print.DocFlavor.STRING;
+
+import static org.junit.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class JoiningTest {
+    static Connection connection;
+
+    static final String DB_PATH = "/home/patryk/dev/segp14/Campaign.db";
+
+    PreparedStatement queryStatement;
+
+    public PreparedStatement prepareStatement(String code) throws SQLException {
+        return queryStatement = connection.prepareStatement(code);
+    }
+
+    public ResultSet executeQuery() throws SQLException {
+        return queryStatement.executeQuery();
+    }
+
+    @BeforeAll
+    public static void init() {
+        try {
+            connection = CampaignImporter.openConnection(DB_PATH);
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        } catch (SQLException throwables) {
+            throwables.printStackTrace();
+        } 
+    }
+
+    @AfterAll
+    public static void cleanup() {
+        try {
+            connection.close();
+        } catch (SQLException throwables) {
+            throwables.printStackTrace();
+        }
+    }
+    @ParameterizedTest
+    @MethodSource("clickJoinTestData")
+    public void clickJoinTest(String clickDate, String userID, String expectedImpressionDate, String expectedImpressionCost) throws SQLException {
+        /*prepareStatement("SELECT Impression.Date, Impression.Cost FROM Click JOIN Impression ON Click.ImpressionDate = Impression.Date AND Click.ID = Impression.ID WHERE Click.Date = ? AND Click.ID = ?;");
+        queryStatement.setString(1, clickDate);
+        queryStatement.setString(2, userID);
+        ResultSet rs = executeQuery();
+        assertTrue(rs.next());
+        assertEquals(expectedImpressionDate, rs.getString(1));
+        assertEquals(expectedImpressionCost, rs.getString(2));
+        assertFalse(rs.next());*/
+        //ensure there is only one record
+        String statement = "SELECT Impression.Date, Impression.Cost FROM Click JOIN Impression ON Click.ImpressionDate = Impression.Date AND Click.ID = Impression.ID WHERE Click.Date = ? AND Click.ID = ?;";
+        String[] expected = {expectedImpressionDate, expectedImpressionCost};
+        joinTestBase(statement, clickDate, userID, expected);
+    }
+
+    public void joinTestBase(String statement, String sourceDate, String userID, String[] expectedValues) throws SQLException {
+        prepareStatement(statement);
+        queryStatement.setString(1, sourceDate);
+        queryStatement.setString(2, userID);
+        ResultSet rs = executeQuery();
+        assertTrue(rs.next());
+        assertEquals(expectedValues[0], rs.getString(1));
+        assertEquals(expectedValues[1], rs.getString(2));
+        assertFalse(rs.next());
+    }
+    public static Stream<Arguments> clickJoinTestData() {
+        return Stream.of(
+            Arguments.of("2015-01-01 12:01:21", "8895519749317550080", "2015-01-01 12:01:18", "0.0"), // 1 imp, 1 click
+            Arguments.of("2015-01-03 23:10:54", "31338434024650752", "2015-01-03 23:10:12", "0.0"), // 4 imp, 1 click
+            Arguments.of("2015-01-07 18:32:58", "6526024657350494208", "2015-01-07 18:32:56", "0.001409"),//3 clicks
+            Arguments.of("2015-01-02 10:06:03", "6526024657350494208", "2015-01-02 10:06:01", "0.000998")
+        );
+            //Arguments.of("2015-01-05 18:14:05", "891294160134144", "2015-01-05 18:13:57", "0.00232"), //2 imp
+    }
+
+    @ParameterizedTest
+    @MethodSource("serverLogJoinTestData")
+    public void serverLogJoinTest(String entryDate, String userID, String expectedClickDate, String expectedClickCost) throws SQLException {
+        var statement = "SELECT Click.Date, Click.ClickCost FROM ServerLog JOIN Click ON ServerLog.ImpressionDate = Click.ImpressionDate AND ServerLog.ID = Click.ID WHERE ServerLog.EntryDate = ? AND ServerLog.ID = ?;";
+        String[] expectedValues = {expectedClickDate, expectedClickCost};
+        joinTestBase(statement, entryDate, userID, expectedValues);
+    }
+
+    public static Stream<Arguments> serverLogJoinTestData() {
+        return Stream.of(
+            Arguments.of("2015-01-01 12:05:51", "4033231570324092928",   "2015-01-01 12:05:51", "14.570611"), //only one click
+            Arguments.of("2015-01-06 12:33:28", "131997838781942784", "2015-01-06 12:33:27", "0.0"), //2 clicks
+            Arguments.of("2015-01-02 10:06:04","6526024657350494208", "2015-01-02 10:06:03",  "0.0"), // 3 clicks
+            Arguments.of("2015-01-07 18:33:01","6526024657350494208", "2015-01-07 18:32:58",  "0.0") // same id, different click should have different time
+        );
+    }
+    
+}