diff --git a/Classes/Domain/Repository/NewsRepository.php b/Classes/Domain/Repository/NewsRepository.php
index 25da9fb7a147ccf182ba84dfc550157f596ac1be..e09d74ed202021388ab892896c9df4e578126b33 100644
--- a/Classes/Domain/Repository/NewsRepository.php
+++ b/Classes/Domain/Repository/NewsRepository.php
@@ -28,6 +28,9 @@ namespace SGalinski\SgNews\Domain\Repository;
 
 use SGalinski\SgNews\Domain\Model\Author;
 use SGalinski\SgNews\Domain\Model\News;
+use TYPO3\CMS\Core\Database\Connection;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Extbase\Persistence\Generic\QueryResult;
 use TYPO3\CMS\Extbase\Persistence\QueryInterface;
 use TYPO3\CMS\Extbase\Persistence\QueryResultInterface;
@@ -514,23 +517,71 @@ class NewsRepository extends AbstractRepository {
 	 * @return QueryResultInterface
 	 */
 	public function findRelated(News $news, int $limit = 0) {
+		$connection = $this->getConnection();
+		$qb = $connection->createQueryBuilder();
+		$constraints = [];
+		$tags = $news->getTags();
+		if ($tags->count() > 0) {
+			$tagConstraints = [];
+			foreach ($tags as $tag) {
+				$qb->leftJoin('pages', 'sys_category_records_mm', 'tags', 'pages.uid=tags.uid_foreign');
+				$tagConstraints[] = $qb->expr()->eq('tags.uid_local', $tag->getUid());
+			}
+			$constraints[] = $qb->expr()->eq('tags.tablenames', $qb->createNamedParameter('pages'));
+			$constraints[] = $qb->expr()->eq('tags.fieldname', $qb->createNamedParameter('tx_sgnews_tags'));
+			$constraints[] = $qb->expr()->orX($tagConstraints);
+		} else {
+			$constraints[] = $qb->expr()->eq('pid', $news->getPid());
+		}
+
+		$result = $qb->select('lastUpdated')
+			->from('pages')
+			->where(
+				$qb->expr()->eq('doktype', $qb->createNamedParameter(News::DOK_TYPE_NEWS, Connection::PARAM_INT)),
+				$qb->expr()->gt('lastUpdated', $news->getLastUpdated()->getTimestamp()),
+				$qb->expr()->andX(...$constraints)
+			)
+			->setMaxResults($limit)
+			->orderBy('lastUpdated', 'asc')
+			->execute();
+		$max = $result->fetchOne();
+
+		$result = $qb->select('lastUpdated')
+			->from('pages')
+			->where(
+				$qb->expr()->eq('doktype', $qb->createNamedParameter(News::DOK_TYPE_NEWS, Connection::PARAM_INT)),
+				$qb->expr()->lt('lastUpdated', $news->getLastUpdated()->getTimestamp()),
+				$qb->expr()->andX(...$constraints)
+			)
+			->setMaxResults($limit)
+			->orderBy('lastUpdated', 'desc')
+			->execute();
+		$min = $result->fetchOne();
+
 		$query = $this->createQuery();
 		$query->getQuerySettings()->setRespectStoragePage(FALSE);
 		$query->setOrderings([
 			'crdate' => QueryInterface::ORDER_DESCENDING
 		]);
-		$contains = [];
+		$constraints = [];
+		if ($max) {
+			$constraints[] = $query->lessThan('lastUpdated', $max);
+		}
+		if ($min) {
+			$constraints[] = $query->greaterThan('lastUpdated', $min);
+		}
+
 		$tags = $news->getTags();
 		if ($tags->count() > 0) {
 			foreach ($tags as $tag) {
-				$contains[] = $query->contains('tags', $tag);
+				$constraints[] = $query->contains('tags', $tag);
 			}
 		} else {
-			$contains[] = $query->equals('pid', $news->getPid());
+			$constraints[] = $query->equals('pid', $news->getPid());
 		}
 
 		$query->matching(
-			$contains
+			$constraints
 		);
 		if ($limit > 0) {
 			$query->setLimit($limit);
@@ -538,4 +589,9 @@ class NewsRepository extends AbstractRepository {
 
 		return $query->execute();
 	}
+
+	protected function getConnection(): Connection {
+		return GeneralUtility::makeInstance(ConnectionPool::class)
+			->getConnectionForTable('pages');
+	}
 }
diff --git a/Classes/ViewHelpers/RelatedViewHelper.php b/Classes/ViewHelpers/RelatedViewHelper.php
new file mode 100644
index 0000000000000000000000000000000000000000..f49aeecbb0ba4c8109d328bceabf4588c9232f23
--- /dev/null
+++ b/Classes/ViewHelpers/RelatedViewHelper.php
@@ -0,0 +1,64 @@
+<?php
+
+namespace SGalinski\SgNews\ViewHelpers;
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
+
+class RelatedViewHelper extends AbstractViewHelper {
+	/**
+	 * Initialize the view helper arguments
+	 */
+	public function initializeArguments() {
+		$this->registerArgument(
+			'news',
+			'SGalinski\SgNews\Domain\Model\News',
+			'The news record from which to find related news',
+			TRUE
+		);
+		$this->registerArgument('limit', 'int', 'Limit the amount of related news to display', FALSE, 5);
+		$this->registerArgument('as', 'string', 'The name of the iteration variable', TRUE);
+		$this->registerArgument('iteration', 'string', 'The name of the variable to store iteration information (index, cycle, isFirst, isLast, isEven, isOdd)');
+	}
+
+	/**
+	 * Render the ViewHelper
+	 * It works like the for-ViewHelper by running through the child content and adding the related news records to it
+	 *
+	 * @return string
+	 */
+	public function render() {
+		$news = $this->arguments['news'];
+		$newsRepository = GeneralUtility::makeInstance(NewsRepository::class);
+		$related = $newsRepository->findRelated($news);
+		$templateVariableContainer = $this->renderingContext->getVariableProvider();
+		$output = '';
+		if (isset($this->arguments['iteration'])) {
+            $iterationData = [
+                'index' => 0,
+                'cycle' => 1,
+                'total' => count($related)
+            ];
+        }
+		foreach ($related as $relatedNews) {
+			$templateVariableContainer->add($this->arguments['as'], $relatedNews);
+			if (isset($this->arguments['iteration'])) {
+                $iterationData['isFirst'] = $iterationData['cycle'] === 1;
+                $iterationData['isLast'] = $iterationData['cycle'] === $iterationData['total'];
+                $iterationData['isEven'] = $iterationData['cycle'] % 2 === 0;
+                $iterationData['isOdd'] = !$iterationData['isEven'];
+                $templateVariableContainer->add($this->arguments['iteration'], $iterationData);
+                $iterationData['index']++;
+                $iterationData['cycle']++;
+            }
+
+            $output .= $this->renderChildren();
+            $templateVariableContainer->remove($this->arguments['as']);
+			if (isset($this->arguments['iteration'])) {
+                $templateVariableContainer->remove($this->arguments['iteration']);
+            }
+		}
+
+		return $output;
+	}
+}