diff --git a/src/main/java/it/unibz/inf/isochrone/algorithm/Isochrone.java b/src/main/java/it/unibz/inf/isochrone/algorithm/Isochrone.java
index 6ef169d1760a17f75101be2160406ee151d1572d..a4eaa433f1ff864abf7f0daab8c03469005a00af 100644
--- a/src/main/java/it/unibz/inf/isochrone/algorithm/Isochrone.java
+++ b/src/main/java/it/unibz/inf/isochrone/algorithm/Isochrone.java
@@ -14,8 +14,6 @@ import it.unibz.inf.isochrone.util.Query;
 
 import java.util.Calendar;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -158,17 +156,40 @@ public abstract class Isochrone {
 		qStartNodes.initialize(output);
 
 		Node node = null;
+		NodeConnection cConnections = null;
+		NodeConnection dConnections = null;
 		while ((node = nodeQueue.poll()) != null) {
 			final int nodeId = node.getId();
+			cConnections = new NodeConnection(node);
+			dConnections = new NodeConnection(node);
+
 			final Collection<Link> adjacents = calcAdjLinks(nodeId);
 			output.addNode(node);
 			node.close();
 
-			final NodeConnection nConnection = prepareLinkExpand(node, adjacents);
-			updateNodeQueue(expandContinuousLinks(nConnection));
-			addLinks(output, adjacents);
+			for (final Link link : adjacents) {
+				final boolean isContLink = link.isContinuous();
+				final Node targetNode = getNode(link.getOppositeOf(node));
+				targetNode.visitNrAdjacentLinks((short) 1);
+
+				if (isContLink) {
+					prepareContinousLink(node, link);
+				}
+
+				if (!targetNode.isClosed()) {
+					if (isContLink) {
+						cConnections.addLink(targetNode, link);
+					} else {
+						dConnections.addLink(targetNode, link);
+					}
+				} else if (qIsExpiring && targetNode.isExpired()) {
+					removeNode(targetNode.getId());
+				}
+			}
 
-			updateNodeQueue(expandDiscreteLinks(nConnection));
+			updateNodeQueue(expandContinuousLinks(cConnections));
+			addLinks(output, cConnections.getAllLinks());
+			updateNodeQueue(expandDiscreteLinks(dConnections));
 
 			if (qIsExpiring && node.isExpired()) {
 				removeNode(nodeId);
@@ -209,75 +230,33 @@ public abstract class Isochrone {
 
 	// Private methods
 
-	private <T extends IOutput> void addLinks(final T output, final Collection<Link> links) {
-		for (final Link link : links) {
-			if (link.isContinuous() && Math.abs(link.getStartOffset() - Double.MIN_VALUE) < COMPARE_PRECISION) {
-				output.addLink(link);
-			}
-		}
-	}
-
-	private NodeConnection prepareLinkExpand(final Node node, final Collection<Link> links) {
-		final NodeConnection nConnection = new NodeConnection(node);
-		for (final Link link : links) {
-			final Node adjacentNode = getNode(link.getOppositeOf(node));
-			adjacentNode.visitNrAdjacentLinks((short) 1);
-
-			if (link.isContinuous()) {
-				final double nodeDistance = node.getDistance();
-				final double linkLength = link.getLength();
-
-				if (qIsIncoming) {
-					link.setStartOffset(Math.max(0, linkLength - (qDuration - nodeDistance) * qWalkingSpeed));
-					link.setEndOffset(linkLength);
-				} else {
-					final double remainingDistance = qDuration - nodeDistance < 0 ? 0 : qDuration - nodeDistance;
-					link.setStartOffset(0);
-					link.setEndOffset(Math.min(linkLength, remainingDistance * qWalkingSpeed));
-				}
-			}
-
-			if (adjacentNode.isClosed()) {
-				if (qIsExpiring && adjacentNode.isExpired() && adjacentNode.getId() != node.getId()) {
-					removeNode(adjacentNode.getId());
-				}
-			} else {
-				nConnection.addTargetLink(adjacentNode, link);
-			}
-		}
-
-		return nConnection;
-	}
-
 	/**
 	 * Expand the given continuous link (that is connected to the given node)
 	 * and adjusts the link offsets based on the distance of the current Node
 	 * and the maximum duration of the query.
 	 *
-	 * @param nConnection information about the the sourceNode, its links and reachable nodes
+	 * @param nConnection information about to where start the calculation, where to travel to and which routes are considered
 	 * @return another node, if it can be reached in the available time (or null if time has run out)
 	 */
 	private Collection<Node> expandContinuousLinks(final NodeConnection nConnection) {
-		if (!nConnection.containsContinuousTargets()) {
-			return Collections.emptyList();
-		}
-
-		final Set<Node> resultCollection = new HashSet<>();
-		final Node sourceNode = nConnection.getSourceNode();
-		final Set<Entry<Node, Collection<Link>>> entrySet = nConnection.getContinuousTargets().entrySet();
-		for (final Entry<Node, Collection<Link>> e : entrySet) {
-			final Node adjacentNode = e.getKey();
-			final Collection<Link> linkCollection = e.getValue();
-			for (final Link link : linkCollection) {
-				final double newDistance = sourceNode.getDistance() + link.getLength() / qWalkingSpeed;
-				if (newDistance <= qDuration && newDistance < adjacentNode.getDistance()) {
-					adjacentNode.setDistance(newDistance);
-					resultCollection.add(adjacentNode);
+		final double sourceDistance = nConnection.getSourceNode().getDistance();
+		final Map<Node, Collection<Link>> targets = nConnection.getTargetEntries();
+		final Collection<Entry<Node, Collection<Link>>> entries = targets.entrySet();
+
+		final Set<Node> results = new LinkedHashSet<>(targets.size());
+		for (final Entry<Node, Collection<Link>> e : entries) {
+			final Node targetNode = e.getKey();
+			final Collection<Link> targetLinks = e.getValue();
+			for (final Link l : targetLinks) {
+				final double newDistance = sourceDistance + l.getLength() / qWalkingSpeed;
+				if (newDistance <= qDuration && newDistance < targetNode.getDistance()) {
+					targetNode.setDistance(newDistance);
+					results.add(targetNode);
 				}
 			}
 		}
 
-		return resultCollection;
+		return results;
 	}
 
 	/**
@@ -286,46 +265,44 @@ public abstract class Isochrone {
 	 * distance of the current Node and the maximum duration of
 	 * the query.
 	 *
-	 * @param nConnection information about the the sourceNode, its links and reachable nodes
-	 * @return all nodes that can be reached in the available time (or an empty set if there is no time to reach another node)
+	 * @param nConnection information about to where start the calculation, where to travel to and which routes are considered
+	 * @return another node, if it can be reached in the available time (or null if there is no time to reach another node)
 	 */
 	private Collection<Node> expandDiscreteLinks(final NodeConnection nConnection) {
-		if (!nConnection.containsDiscreteTargets()) {
-			return Collections.emptyList();
-		}
-
-		final Map<Node, Double> newDistances = getAdjNodeCost(nConnection);
-		final Set<Node> resultCollection = new LinkedHashSet<>(newDistances.size());
-		for (final Entry<Node, Double> e : newDistances.entrySet()) {
-			final Node adjacentNode = e.getKey();
-			final double newDistance = e.getValue();
-			if (newDistance <= qDuration && newDistance < adjacentNode.getDistance()) {
-				adjacentNode.setDistance(newDistance);
-				resultCollection.add(adjacentNode);
+		final Map<Node, Long> newDistances = getAdjNodeCost(nConnection);
+		final Collection<Entry<Node, Long>> entries = newDistances.entrySet();
+
+		final Set<Node> results = new LinkedHashSet<>(newDistances.size());
+		for (final Entry<Node, Long> entry : entries) {
+			final Node targetNode = entry.getKey();
+			final Long newDistance = entry.getValue();
+			if (newDistance <= qDuration && newDistance < targetNode.getDistance()) {
+				targetNode.setDistance(newDistance);
+				results.add(targetNode);
 			}
 		}
 
-		return resultCollection;
+		return results;
 	}
 
 	/**
-	 * Gets date codes for a given time.
+	 * Get the cost to travel to an adjacent node.
 	 *
-	 * @param time the given
-	 * @return returns a set of date codes
+	 * @param nConnection information about to where start the calculation, where to travel to and which routes are considered
+	 * @return the cost of traveling from the node to the target nodes (targetNodeId == mapKey, distance == mapValue)
 	 */
-	private Collection<Integer> getDateCodes(final Calendar time) {
-		return database.getDateCodes(time);
+	private Map<Node, Long> getAdjNodeCost(final NodeConnection nConnection) {
+		return database.getAdjNodeCost(nConnection, dateCodes, qFromTime, qToTime);
 	}
 
 	/**
-	 * Get the cost to travel to an adjacent node.
+	 * Gets date codes for a given time.
 	 *
-	 * @param nConnection information about to where start the calculation, where to travel to and which routes are considered
-	 * @return the cost of traveling from the node to adjNode
+	 * @param time the given
+	 * @return returns a set of date codes
 	 */
-	private Map<Node, Double> getAdjNodeCost(final NodeConnection nConnection) {
-		return database.getAdjNodeCost(nConnection, dateCodes, qFromTime, qToTime);
+	private Collection<Integer> getDateCodes(final Calendar time) {
+		return database.getDateCodes(time);
 	}
 
 	/**
@@ -377,17 +354,33 @@ public abstract class Isochrone {
 		}
 	}
 
+	private void prepareContinousLink(final Node node, final Link link) {
+		final double linkLength = link.getLength();
+		final double nodeDistance = node.getDistance();
+
+		if (qIsIncoming) {
+			link.setStartOffset(Math.max(0, linkLength - (qDuration - nodeDistance) * qWalkingSpeed));
+			link.setEndOffset(linkLength);
+		} else {
+			final double remainingDistance = qDuration - nodeDistance < 0 ? 0 : qDuration - nodeDistance;
+			link.setStartOffset(0);
+			link.setEndOffset(Math.min(linkLength, remainingDistance * qWalkingSpeed));
+		}
+	}
+
 	/**
-	 * Set an updated node into the right place in the priority
+	 * Sets an updated node into the right place in the priority
 	 * queue.
 	 *
 	 * @param node The node that was changed
 	 */
 	private void updateNodeQueue(final Node node) {
-		if (node != null) {
-			nodeQueue.remove(node);
-			nodeQueue.offer(node);
+		if (node == null) {
+			return;
 		}
+
+		nodeQueue.remove(node);
+		nodeQueue.offer(node);
 	}
 
 	/**
@@ -396,8 +389,22 @@ public abstract class Isochrone {
 	 * @param nodes The nodes that were changed
 	 */
 	private void updateNodeQueue(final Collection<Node> nodes) {
+		if (nodes == null || nodes.isEmpty()) {
+			return;
+		}
+
 		for (final Node node : nodes) {
 			updateNodeQueue(node);
 		}
 	}
+
+	// Private static methods
+
+	private static <T extends AbstractOutput> void addLinks(final T output, final Collection<Link> links) {
+		for (final Link link : links) {
+			if (Math.abs(link.getStartOffset() - Double.MIN_VALUE) < COMPARE_PRECISION) {
+				output.addLink(link);
+			}
+		}
+	}
 }
diff --git a/src/main/java/it/unibz/inf/isochrone/db/Database.java b/src/main/java/it/unibz/inf/isochrone/db/Database.java
index 61d5560ba05e4a8473dfc8700087e600d93cabaf..d2144e24263190403510740c9d29727e79ac9aa5 100644
--- a/src/main/java/it/unibz/inf/isochrone/db/Database.java
+++ b/src/main/java/it/unibz/inf/isochrone/db/Database.java
@@ -20,7 +20,9 @@ import java.util.Calendar;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 /**
@@ -40,10 +42,13 @@ import java.util.Set;
  * @version 2.2
  */
 public class Database {
+	private static final boolean USE_IN_QUERY = false;
 	protected static final byte NW_MODE_CONTINUOUS = 0;
 	protected static final byte NW_MODE_DISCRETE = 1;
 	private final String queryEarliestArrivalTimeHomo;
+	private final String queryEarliestArrivalTimeHomoInQuery;
 	private final String queryLatestDepartureTimeHomo;
+	private final String queryLatestDepartureTimeHomoInQuery;
 	private final String queryGetAllEdges;
 	private final String queryGetAdjLinks;
 	private final String queryGetAdjContinuousLinks;
@@ -57,13 +62,14 @@ public class Database {
 	private final String queryGetLinksInRange;
 	private final String queryGetRange;
 	private final String queryLoadLinksFromIER;
-	protected final ConfigDataset config;
-	protected Mode mode;
-	protected boolean isIncoming;
 	private Map<String, PreparedStatement> pstmtsCacheMap;
 	/** The connection the the database. It is lazy-loaded by {@link #getPstmt(String)} method. */
 	private Connection connection;
 
+	protected final ConfigDataset config;
+	protected Mode mode;
+	protected boolean isIncoming;
+
 	// Constructor
 
 	public Database(final ConfigDataset config, final Mode mode, final Direction direction) {
@@ -77,12 +83,18 @@ public class Database {
 		final String configVertex = config.getTableVertex();
 		final String configVertexDensity = config.getTableVertexDensity();
 
-		queryLatestDepartureTimeHomo = "SELECT SOURCE, TARGET, TIME_D, TIME_A, ROUTE_ID FROM " + configSchedule
-				+ " WHERE SOURCE IN (%S) AND TARGET = ? AND ROUTE_ID IN (%S) AND TIME_A>=? AND TIME_A<=? AND SERVICE_ID IN (%S) AND TIME_D >= ?";
+		queryEarliestArrivalTimeHomo = "SELECT TIME_D, TIME_A, ROUTE_ID FROM " + configSchedule
+				+ " WHERE SOURCE = ? AND TARGET = ? AND ROUTE_ID IN (%S) AND TIME_D>=? AND TIME_D<=? AND SERVICE_ID IN (%S) AND TIME_A <= ?";
 
-		queryEarliestArrivalTimeHomo = "SELECT SOURCE, TARGET, TIME_D, TIME_A, ROUTE_ID FROM " + configSchedule
+		queryEarliestArrivalTimeHomoInQuery = "SELECT SOURCE, TARGET, TIME_D, TIME_A, ROUTE_ID FROM " + configSchedule
 				+ " WHERE SOURCE = ? AND TARGET IN (%S) AND ROUTE_ID IN (%S) AND TIME_D>=? AND TIME_D<=? AND SERVICE_ID IN (%S) AND TIME_A <= ?";
 
+		queryLatestDepartureTimeHomo = "SELECT TIME_D, TIME_A, ROUTE_ID FROM " + configSchedule
+				+ " WHERE SOURCE = ? AND  TARGET = ? AND ROUTE_ID IN (%S) AND TIME_A>=? AND TIME_A<=? AND SERVICE_ID IN (%S) AND TIME_D >= ?";
+
+		queryLatestDepartureTimeHomoInQuery = "SELECT SOURCE, TARGET, TIME_D, TIME_A, ROUTE_ID FROM " + configSchedule
+				+ " WHERE SOURCE IN (%S) AND TARGET = ? AND ROUTE_ID IN (%S) AND TIME_A>=? AND TIME_A<=? AND SERVICE_ID IN (%S) AND TIME_D >= ?";
+
 		queryGetAllEdges = "SELECT ID, SOURCE, TARGET, LENGTH, EDGE_MODE, ROUTE_ID FROM " + configEdges;
 
 		queryGetContinuousEdges = "SELECT ID, SOURCE, TARGET, LENGTH, EDGE_MODE, ROUTE_ID FROM " + configEdges + " WHERE EDGE_MODE=" + NW_MODE_CONTINUOUS;
@@ -152,7 +164,7 @@ public class Database {
 
 	// Public methods
 
-	public void addLink(final Link link, final short degree, final Map<Integer, Node> nodes, final Map<Integer, Collection<Link>> adjList) {
+	private void addLink(final Link link, final short degree, final Map<Integer, Node> nodes, final Map<Integer, Collection<Link>> adjList) {
 		int n1, n2;
 		if (isIncoming) {
 			n1 = link.getStartNode();
@@ -218,70 +230,17 @@ public class Database {
 	/**
 	 * Gets the cost to go from one node to another node.
 	 *
-	 * @param nConnection information about to where start the calculation, where to travel to and which routes are considered
 	 * @param dateCodes the days that should be taken into the account
 	 * @param fromTime the earliest time for which we want to calculate the departure time
 	 * @param toTime the latest time for which we want to calculate the departure time
 	 * @return the cost of for traveling from the start node to the end node
 	 */
-	public Map<Node, Double> getAdjNodeCost(final NodeConnection nConnection, final Collection<Integer> dateCodes, final long fromTime, final long toTime) {
-		final Map<Node, Double> resultMap = new HashMap<>();
-		final Node node = nConnection.getSourceNode();
-
-		ResultSet rs = null;
-		try {
-			if (isIncoming) {
-				rs = getLatestDepartureTime(nConnection, dateCodes, fromTime, Math.round(toTime - node.getDistance()));
-				while (rs.next()) {
-					final long departureTime = rs.getLong("TIME_D");
-					final long arrivalTime = rs.getLong("TIME_A");
-					final int routeId = rs.getInt("ROUTE_ID");
-					final int adjNodeId = rs.getInt("SOURCE");
-					final Node adjNode = nConnection.getDiscreteTargetNode(adjNodeId);
-					adjNode.setDepartureTime(routeId, departureTime);
-					node.setArrivalTime(routeId, arrivalTime);
-
-					Double minDistance = resultMap.get(adjNode);
-					if (minDistance == null) {
-						minDistance = Double.POSITIVE_INFINITY;
-					}
-
-					final double distance = toTime - departureTime;
-					if (distance < minDistance) {
-						resultMap.put(adjNode, distance);
-						adjNode.setCheapestReachedRouteId(routeId);
-					}
-				}
-			} else {
-				rs = getEarliestArrivalTime(nConnection, dateCodes, Math.round(fromTime + node.getDistance()), toTime);
-				while (rs.next()) {
-					final long departureTime = rs.getLong("TIME_D");
-					final long arrivalTime = rs.getLong("TIME_A");
-					final int routeId = rs.getInt("ROUTE_ID");
-					final int adjNodeId = rs.getInt("TARGET");
-					final Node adjNode = nConnection.getDiscreteTargetNode(adjNodeId);
-					node.setDepartureTime(routeId, departureTime);
-					adjNode.setArrivalTime(routeId, arrivalTime);
-
-					Double minDistance = resultMap.get(adjNode);
-					if (minDistance == null) {
-						minDistance = Double.POSITIVE_INFINITY;
-					}
-
-					final double distance = arrivalTime > 0 ? arrivalTime - fromTime : Double.POSITIVE_INFINITY;
-					if (distance < minDistance) {
-						resultMap.put(adjNode, distance);
-						adjNode.setCheapestReachedRouteId(routeId);
-					}
-				}
-			}
-		} catch (final SQLException e) {
-			e.printStackTrace();
-		} finally {
-			DbUtils.closeQuietly(rs);
+	public Map<Node, Long> getAdjNodeCost(final NodeConnection nConnection, final Collection<Integer> dateCodes, final long fromTime, final long toTime) {
+		if (USE_IN_QUERY) {
+			return getAdjNodeCostByInQuery(nConnection, dateCodes, fromTime, toTime);
 		}
 
-		return resultMap;
+		return getAdjNodeCostByLoops(nConnection, dateCodes, fromTime, toTime);
 	}
 
 	/**
@@ -342,67 +301,6 @@ public class Database {
 		return codes;
 	}
 
-	/**
-	 * Gets the earliest arrival time at the target when traveled from the source.
-	 *
-	 * @param nConnection (contains the source node id, the targetIds and the route ids)
-	 * @param dates the date codes for which the times are calculated
-	 * @param from the earliest time for which we want to calculate the departure time
-	 * @param to the latest time for which we want to calculate the departure time
-	 * @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set)
-	 * @return a resultSet with all the times that come into consideration
-	 */
-	public ResultSet getEarliestArrivalTime(final NodeConnection nConnection, final Collection<Integer> dates, final long from, final long to) throws SQLException {
-		final int sId = nConnection.getSourceNode().getId();
-		final Collection<Integer> tIds = nConnection.getDiscreteTargetNodeIds();
-		final Collection<Integer> rIds = nConnection.getDiscreteRouteIds();
-
-		final String sql = String.format(queryEarliestArrivalTimeHomo, preparePlaceHolders(tIds.size()), preparePlaceHolders(rIds.size()), preparePlaceHolders(dates.size()));
-		final PreparedStatement statement = getPstmt(sql);
-
-		// CHECKSTYLE:OFF MagicNumber
-		statement.setInt(1, sId);
-		int idx = setValues(2, statement, tIds.toArray());
-		idx = setValues(idx, statement, rIds.toArray());
-		statement.setLong(idx++, from);
-		statement.setLong(idx++, to);
-		idx = setValues(idx, statement, dates.toArray());
-		statement.setLong(idx, to);
-		// CHECKSTYLE:ON MagicNumber
-
-		return statement.executeQuery();
-	}
-
-	/**
-	 * Gets the latest departure time to start from source, to arrive at the target in time.
-	 *
-	 * @param nConnection (contains the sourceIds, the target node id and the route ids)
-	 * @param dates the date codes for which the times are calculated
-	 * @param from the earliest time for which we want to calculate the departure time
-	 * @param to the latest time for which we want to calculate the departure time
-	 * @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set)
-	 * @return a resultSet with all the times that come into consideration
-	 */
-	public ResultSet getLatestDepartureTime(final NodeConnection nConnection, final Collection<Integer> dates, final long from, final long to) throws SQLException {
-		final int tId = nConnection.getSourceNode().getId();
-		final Collection<Integer> sIds = nConnection.getDiscreteTargetNodeIds();
-		final Collection<Integer> routeIds = nConnection.getDiscreteRouteIds();
-
-		final String sql = String.format(queryLatestDepartureTimeHomo, preparePlaceHolders(sIds.size()), preparePlaceHolders(routeIds.size()), preparePlaceHolders(dates.size()));
-		final PreparedStatement statement = getPstmt(sql);
-
-		// CHECKSTYLE:OFF MagicNumber
-		int idx = setValues(1, statement, sIds.toArray());
-		statement.setInt(idx++, tId);
-		idx = setValues(idx, statement, routeIds.toArray());
-		statement.setLong(idx++, from);
-		statement.setLong(idx++, to);
-		idx = setValues(idx, statement, dates.toArray());
-		statement.setLong(idx, from);
-		// CHECKSTYLE:ON MagicNumber
-
-		return statement.executeQuery();
-	}
 
 	/**
 	 * Get a single link from the network and and add the source
@@ -425,7 +323,12 @@ public class Database {
 				final int targetId = rs.getInt("TARGET");
 				final short degree = rs.getShort("NODE_DEGREE");
 				final double length = rs.getDouble("LENGTH");
-				addNode((isIncoming) ? sourceId : targetId, degree, nodes);
+				if (isIncoming) {
+					addNode(sourceId, degree, nodes);
+				} else {
+					addNode(targetId, degree, nodes);
+				}
+
 				link = new Link(linkId, sourceId, targetId, length);
 			}
 		} catch (final SQLException e) {
@@ -714,6 +617,216 @@ public class Database {
 		return new Link(linkId, start, end, routeId);
 	}
 
+	private Map<Node, Long> getAdjNodeCostByInQuery(final NodeConnection nConnection, final Collection<Integer> dateCodes, final long fromTime, final long toTime) {
+		final Map<Node, Long> results = new LinkedHashMap<>();
+		final Node node = nConnection.getSourceNode();
+
+		ResultSet rs = null;
+		try {
+			if (isIncoming) {
+				rs = getLatestDepartureTime(nConnection, dateCodes, fromTime, Math.round(toTime - node.getDistance()));
+				while (rs.next()) {
+					final long departureTime = rs.getLong("TIME_D");
+					final long arrivalTime = rs.getLong("TIME_A");
+					final int routeId = rs.getInt("ROUTE_ID");
+					final int adjNodeId = rs.getInt("SOURCE");
+					final Node adjNode = nConnection.getTargetNode(adjNodeId);
+					adjNode.setDepartureTime(routeId, departureTime);
+					node.setArrivalTime(routeId, arrivalTime);
+
+					final long distance = toTime - departureTime;
+					updateDistanceMap(results, routeId, adjNode, distance);
+				}
+			} else {
+				rs = getEarliestArrivalTime(nConnection, dateCodes, Math.round(fromTime + node.getDistance()), toTime);
+				while (rs.next()) {
+					final long departureTime = rs.getLong("TIME_D");
+					final long arrivalTime = rs.getLong("TIME_A");
+					final int routeId = rs.getInt("ROUTE_ID");
+					final int adjNodeId = rs.getInt("TARGET");
+					final Node adjNode = nConnection.getTargetNode(adjNodeId);
+					node.setDepartureTime(routeId, departureTime);
+					adjNode.setArrivalTime(routeId, arrivalTime);
+
+					final long distance = arrivalTime > 0 ? arrivalTime - fromTime : Long.MAX_VALUE;
+					updateDistanceMap(results, routeId, adjNode, distance);
+				}
+			}
+		} catch (final SQLException e) {
+			e.printStackTrace();
+		} finally {
+			DbUtils.closeQuietly(rs);
+		}
+
+		return results;
+	}
+
+	private Map<Node, Long> getAdjNodeCostByLoops(final NodeConnection nConnection, final Collection<Integer> dateCodes, final long fromTime, final long toTime) {
+		final Node node = nConnection.getSourceNode();
+		final Set<Entry<Node, Collection<Link>>> entries = nConnection.getTargetEntries().entrySet();
+		final Map<Node, Long> results = new LinkedHashMap<>(entries.size());
+		for (final Entry<Node, Collection<Link>> entry : entries) {
+			final Node targetNode = entry.getKey();
+			final Collection<Integer> routes = NodeConnection.getTargetRoutes(entry.getValue());
+
+			ResultSet rs = null;
+			try {
+				if (isIncoming) {
+					rs = getLatestDepartureTime(targetNode.getId(), node.getId(), routes, dateCodes, fromTime, Math.round(toTime - node.getDistance()));
+					while (rs.next()) {
+						final long departureTime = rs.getLong("TIME_D");
+						final long arrivalTime = rs.getLong("TIME_A");
+						final short routeId = rs.getShort("ROUTE_ID");
+						targetNode.setDepartureTime(routeId, departureTime);
+						node.setArrivalTime(routeId, arrivalTime);
+
+						final long distance = toTime - departureTime;
+						updateDistanceMap(results, routeId, targetNode, distance);
+					}
+				} else {
+					rs = getEarliestArrivalTime(node.getId(), targetNode.getId(), routes, dateCodes, Math.round(fromTime + node.getDistance()), toTime);
+					while (rs.next()) {
+						final long departureTime = rs.getLong("TIME_D");
+						final long arrivalTime = rs.getLong("TIME_A");
+						final short routeId = rs.getShort("ROUTE_ID");
+						targetNode.setArrivalTime(routeId, arrivalTime);
+						node.setDepartureTime(routeId, departureTime);
+
+						final long distance = arrivalTime > 0 ? arrivalTime - fromTime : Long.MAX_VALUE;
+						updateDistanceMap(results, routeId, targetNode, distance);
+					}
+				}
+			} catch (final SQLException e) {
+				e.printStackTrace();
+			} finally {
+				DbUtils.closeQuietly(rs);
+			}
+		}
+
+		return results;
+	}
+
+	/**
+	 * Gets the earliest arrival time at the target when traveled from the source.
+	 *
+	 * @param sId the id of the source node
+	 * @param tId the id of the target node
+	 * @param rIds the identifiers of the routes that should be considered
+	 * @param dateCodes the date codes for which the times are calculated
+	 * @param from the earliest time for which we want to calculate the departure time
+	 * @param to the latest time for which we want to calculate the departure time
+	 * @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set)
+	 * @return a resultSet with all the times that come into consideration
+	 */
+	private ResultSet getEarliestArrivalTime(final int sId, final int tId, final Collection<Integer> rIds, final Collection<Integer> dateCodes, final long from, final long to) throws SQLException {
+		final String sql = String.format(queryEarliestArrivalTimeHomo, preparePlaceHolders(rIds.size()), preparePlaceHolders(dateCodes.size()));
+		final PreparedStatement statement = getPstmt(sql);
+
+		// CHECKSTYLE:OFF MagicNumber
+		statement.setInt(1, sId);
+		statement.setInt(2, tId);
+		int idx = setValues(3, statement, rIds.toArray());
+		statement.setLong(idx++, from);
+		statement.setLong(idx++, to);
+		idx = setValues(idx, statement, dateCodes.toArray());
+		statement.setLong(idx, to);
+		// CHECKSTYLE:ON MagicNumber
+
+		return statement.executeQuery();
+	}
+
+	/**
+	 * Gets the earliest arrival time at the target when traveled from the source.
+	 *
+	 * @param nConnection (contains the source node id, the targetIds and the route ids)
+	 * @param dates the date codes for which the times are calculated
+	 * @param from the earliest time for which we want to calculate the departure time
+	 * @param to the latest time for which we want to calculate the departure time
+	 * @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set)
+	 * @return a resultSet with all the times that come into consideration
+	 */
+	private ResultSet getEarliestArrivalTime(final NodeConnection nConnection, final Collection<Integer> dates, final long from, final long to) throws SQLException {
+		final int sId = nConnection.getSourceNode().getId();
+		final Collection<Integer> tIds = nConnection.getAllTargetNodes();
+		final Collection<Integer> rIds = nConnection.getAllRoutes();
+
+		final String sql = String.format(queryEarliestArrivalTimeHomoInQuery, preparePlaceHolders(tIds.size()), preparePlaceHolders(rIds.size()), preparePlaceHolders(dates.size()));
+		final PreparedStatement statement = getPstmt(sql);
+
+		// CHECKSTYLE:OFF MagicNumber
+		statement.setInt(1, sId);
+		int idx = setValues(2, statement, tIds.toArray());
+		idx = setValues(idx, statement, rIds.toArray());
+		statement.setLong(idx++, from);
+		statement.setLong(idx++, to);
+		idx = setValues(idx, statement, dates.toArray());
+		statement.setLong(idx, to);
+		// CHECKSTYLE:ON MagicNumber
+
+		return statement.executeQuery();
+	}
+
+	/**
+	 * Gets the latest departure time to start from source, to arrive at the target in time.
+	 *
+	 * @param sId the id of the source node
+	 * @param tId the id of the target node
+	 * @param rIds the identifiers of the routes that should be considered
+	 * @param dateCodes the date codes for which the times are calculated
+	 * @param from the earliest time for which we want to calculate the departure time
+	 * @param to the latest time for which we want to calculate the departure time
+	 * @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set)
+	 * @return a resultSet with all the times that come into consideration
+	 */
+	private ResultSet getLatestDepartureTime(final int sId, final int tId, final Collection<Integer> rIds, final Collection<Integer> dateCodes, final long from, final long to) throws SQLException {
+		final String sql = String.format(queryLatestDepartureTimeHomo, preparePlaceHolders(rIds.size()), preparePlaceHolders(dateCodes.size()));
+		final PreparedStatement statement = getPstmt(sql);
+
+		// CHECKSTYLE:OFF MagicNumber
+		statement.setInt(1, sId);
+		statement.setInt(2, tId);
+		int idx = setValues(3, statement, rIds.toArray());
+		statement.setLong(idx++, from);
+		statement.setLong(idx++, to);
+		idx = setValues(idx, statement, dateCodes.toArray());
+		statement.setLong(idx, from);
+		// CHECKSTYLE:ON MagicNumber
+
+		return statement.executeQuery();
+	}
+
+	/**
+	 * Gets the latest departure time to start from source, to arrive at the target in time.
+	 *
+	 * @param nConnection (contains the sourceIds, the target node id and the route ids)
+	 * @param dates the date codes for which the times are calculated
+	 * @param from the earliest time for which we want to calculate the departure time
+	 * @param to the latest time for which we want to calculate the departure time
+	 * @throws SQLException thrown is the DB update statement can not be executed (or the prepared statement parameters could not be set)
+	 * @return a resultSet with all the times that come into consideration
+	 */
+	private ResultSet getLatestDepartureTime(final NodeConnection nConnection, final Collection<Integer> dates, final long from, final long to) throws SQLException {
+		final int tId = nConnection.getSourceNode().getId();
+		final Collection<Integer> sIds = nConnection.getAllTargetNodes();
+		final Collection<Integer> routeIds = nConnection.getAllRoutes();
+
+		final String sql = String.format(queryLatestDepartureTimeHomoInQuery, preparePlaceHolders(sIds.size()), preparePlaceHolders(routeIds.size()), preparePlaceHolders(dates.size()));
+		final PreparedStatement statement = getPstmt(sql);
+
+		// CHECKSTYLE:OFF MagicNumber
+		int idx = setValues(1, statement, sIds.toArray());
+		statement.setInt(idx++, tId);
+		idx = setValues(idx, statement, routeIds.toArray());
+		statement.setLong(idx++, from);
+		statement.setLong(idx++, to);
+		idx = setValues(idx, statement, dates.toArray());
+		statement.setLong(idx, from);
+		// CHECKSTYLE:ON MagicNumber
+
+		return statement.executeQuery();
+	}
+
+
 	// Protected static methods
 
 	/**
@@ -824,4 +937,16 @@ public class Database {
 					+ subQuery(loaded, idx - 1, srid) + ")";
 		}
 	}
+
+	private static void updateDistanceMap(final Map<Node, Long> results, final int routeId, final Node adjNode,  final long distance) {
+		Long minDistance = results.get(adjNode);
+		if (minDistance == null) {
+			minDistance = Long.MAX_VALUE;
+		}
+
+		if (distance < minDistance) {
+			results.put(adjNode, distance);
+			adjNode.setCheapestReachedRouteId(routeId);
+		}
+	}
 }
diff --git a/src/main/java/it/unibz/inf/isochrone/network/NodeConnection.java b/src/main/java/it/unibz/inf/isochrone/network/NodeConnection.java
index 38c92d152759e65740f14a48461e4b8caf63fde8..34ee245d6116881c4e0fe3728d6244e13c8b748b 100644
--- a/src/main/java/it/unibz/inf/isochrone/network/NodeConnection.java
+++ b/src/main/java/it/unibz/inf/isochrone/network/NodeConnection.java
@@ -11,103 +11,73 @@ public class NodeConnection {
 	private static final int INITIAL_LIST_SIZE = 3;
 
 	private final Node sourceNode;
-	private final Map<Node, Collection<Link>> continuousTargetConnections;
-	private final Map<Node, Collection<Link>> discreteTargetConnections;
+	private final Map<Node, Collection<Link>> targetRoutes;
 
 	// Collections
 
 	public NodeConnection(final Node sourceNode) {
 		this.sourceNode = sourceNode;
-		this.continuousTargetConnections = new LinkedHashMap<>();
-		this.discreteTargetConnections = new LinkedHashMap<>();
+		this.targetRoutes = new LinkedHashMap<>();
 	}
 
 	// Getters
 
-	public Node getSourceNode() {
-		return sourceNode;
-	}
-
-	public Map<Node, Collection<Link>> getContinuousTargets() {
-		return continuousTargetConnections;
-	}
-
-	public Collection<Integer> getContinuousRouteToTargetNode(final int nodeId) {
-		return getRoutesToTargetNode(continuousTargetConnections, nodeId);
-	}
-
-	public Node getContinuousTargetNode(final int nodeId) {
-		return getNodeById(continuousTargetConnections, nodeId);
-	}
-
-	public Collection<Integer> getContinuousTargetNodeIds() {
-		return getIdsForTargetNodes(continuousTargetConnections);
-	}
-
-	public Collection<Integer> getContinuousRouteIds() {
-		return getIdsForTargetNodes(continuousTargetConnections);
-	}
+	public Collection<Link> getAllLinks() {
+		final Collection<Collection<Link>> linkSet = targetRoutes.values();
+		final Set<Link> resultSet = new LinkedHashSet<>(linkSet.size());
+		for (final Collection<Link> lCollection : linkSet) {
+			resultSet.addAll(lCollection);
+		}
 
-	public Map<Node, Collection<Link>> getDiscreteTargets() {
-		return discreteTargetConnections;
+		return resultSet;
 	}
 
-	public Node getDiscreteTargetNode(final int nodeId) {
-		return getNodeById(discreteTargetConnections, nodeId);
-	}
+	public Collection<Integer> getAllTargetNodes() {
+		final Set<Node> nodeSet = targetRoutes.keySet();
+		final Set<Integer> resultSet = new LinkedHashSet<>(nodeSet.size());
+		for (final Node n : nodeSet) {
+			resultSet.add(n.getId());
+		}
 
-	public Collection<Integer> getDiscreteTargetNodeIds() {
-		return getIdsForTargetNodes(discreteTargetConnections);
+		return resultSet;
 	}
 
-	public Collection<Integer> getDiscreteRouteIds() {
-		return getIdsForRoutes(discreteTargetConnections);
-	}
+	public Collection<Integer> getAllRoutes() {
+		final Collection<Collection<Link>> linkSet = targetRoutes.values();
+		final Set<Integer> resultSet = new LinkedHashSet<>(linkSet.size());
+		for (final Collection<Link> lCollection : linkSet) {
+			for (final Link l : lCollection) {
+				resultSet.add(l.getRoute());
+			}
+		}
 
-	public Collection<Integer> getDiscreteRouteToTargetNode(final int nodeId) {
-		return getRoutesToTargetNode(discreteTargetConnections, nodeId);
+		return resultSet;
 	}
 
-	public Collection<Integer> getRoutesToTargetNode(final int nodeId) {
-		return getRoutesToTargetNode(getTargets(), nodeId);
+	public Node getSourceNode() {
+		return sourceNode;
 	}
 
-	public Map<Node, Collection<Link>> getTargets() {
-		final Map<Node, Collection<Link>> allTargets = new LinkedHashMap<>();
-		allTargets.putAll(continuousTargetConnections);
-		allTargets.putAll(discreteTargetConnections);
-
-		return allTargets;
+	public Map<Node, Collection<Link>> getTargetEntries() {
+		return targetRoutes;
 	}
 
-	public Collection<Integer> getTargetNodeIds() {
-		return getIdsForTargetNodes(getTargets());
+	public Node getTargetNode(final int targetNodeId) {
+		return getNodeById(targetNodeId);
 	}
 
-	public Collection<Integer> getRouteIds() {
-		return getIdsForRoutes(getTargets());
+	public Collection<Integer> getTargetRoutes(final int targetNodeId) {
+		return getRoutesToTarget(targetNodeId);
 	}
 
 	// Public methods
 
-	public void addTargetLink(final Node targetNode, final Link link) {
-		if (link.isContinuous()) {
-			addLinkForNode(continuousTargetConnections, targetNode, link);
-		} else {
-			addLinkForNode(discreteTargetConnections, targetNode, link);
-		}
+	public void addLink(final Node targetNode, final Link link) {
+		addLinkForNode(targetNode, link);
 	}
 
 	public boolean containsTargets() {
-		return containsContinuousTargets() || containsDiscreteTargets();
-	}
-
-	public boolean containsContinuousTargets() {
-		return !continuousTargetConnections.isEmpty();
-	}
-
-	public boolean containsDiscreteTargets() {
-		return !discreteTargetConnections.isEmpty();
+		return !targetRoutes.isEmpty();
 	}
 
 	@Override
@@ -115,20 +85,30 @@ public class NodeConnection {
 		return "NodeConnection [sourceNode(id)=" + sourceNode.getId() + "]";
 	}
 
-	// Private static methods
+	// Public static methods
 
-	private static void addLinkForNode(final Map<Node, Collection<Link>> m, final Node node, final Link link) {
-		Collection<Link> c = m.get(node);
+	public static Collection<Integer> getTargetRoutes(final Collection<Link> linkSet) {
+		final Set<Integer> resultSet = new LinkedHashSet<>(linkSet.size());
+		for (final Link l : linkSet) {
+			resultSet.add(l.getRoute());
+		}
+		return resultSet;
+	}
+
+	// Private methods
+
+	private void addLinkForNode(final Node node, final Link link) {
+		Collection<Link> c = targetRoutes.get(node);
 		if (c == null) {
 			c = new ArrayList<>(INITIAL_LIST_SIZE);
 		}
 
 		c.add(link);
-		m.put(node, c);
+		targetRoutes.put(node, c);
 	}
 
-	private static Node getNodeById(final Map<Node, Collection<Link>> map, final int nodeId) {
-		final Set<Node> entries = map.keySet();
+	private Node getNodeById(final int nodeId) {
+		final Set<Node> entries = targetRoutes.keySet();
 		for (final Node n : entries) {
 			if (nodeId == n.getId()) {
 				return n;
@@ -138,38 +118,13 @@ public class NodeConnection {
 		return null;
 	}
 
-	private static Collection<Integer> getIdsForRoutes(final Map<Node, Collection<Link>> m) {
-		final Collection<Collection<Link>> linkSet = m.values();
-		final Set<Integer> resultSet = new LinkedHashSet<>(linkSet.size());
-		for (final Collection<Link> lCollection : linkSet) {
-			for (final Link l : lCollection) {
-				resultSet.add(l.getRoute());
-			}
-		}
-
-		return resultSet;
-	}
-
-	private static Collection<Integer> getRoutesToTargetNode(final Map<Node, Collection<Link>> m, final int nodeId) {
-		return getRoutesToTargetNode(m, getNodeById(m, nodeId));
+	private Collection<Integer> getRoutesToTarget(final int targetNodeId) {
+		return getRoutesToTarget(getNodeById(targetNodeId));
 	}
 
-	private static Collection<Integer> getRoutesToTargetNode(final Map<Node, Collection<Link>> m, final Node node) {
-		final Collection<Link> linkSet = m.get(node);
-		final Set<Integer> resultSet = new LinkedHashSet<>(linkSet.size());
-		for (final Link l : linkSet) {
-			resultSet.add(l.getRoute());
-		}
-		return resultSet;
+	private Collection<Integer> getRoutesToTarget(final Node targetNode) {
+		final Collection<Link> linkSet = targetRoutes.get(targetNode);
+		return getTargetRoutes(linkSet);
 	}
 
-	private static Collection<Integer> getIdsForTargetNodes(final Map<Node, Collection<Link>> m) {
-		final Set<Node> nodeSet = m.keySet();
-		final Set<Integer> resultSet = new LinkedHashSet<>(nodeSet.size());
-		for (final Node n : nodeSet) {
-			resultSet.add(n.getId());
-		}
-
-		return resultSet;
-	}
 }