diff --git a/lib/private/db/querybuilder/querybuilder.php b/lib/private/db/querybuilder/querybuilder.php
index 1d97faf77cc2c4d50da953ae479a730179a2a14f..02d8ee4344de5a81b4d770180058e1e2e8ca9c42 100644
--- a/lib/private/db/querybuilder/querybuilder.php
+++ b/lib/private/db/querybuilder/querybuilder.php
@@ -300,6 +300,30 @@ class QueryBuilder implements IQueryBuilder {
 		return $this;
 	}
 
+	/**
+	 * Specifies an item that is to be returned with a different name in the query result.
+	 *
+	 * <code>
+	 *     $qb = $conn->getQueryBuilder()
+	 *         ->selectAlias('u.id', 'user_id')
+	 *         ->from('users', 'u')
+	 *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
+	 * </code>
+	 *
+	 * @param mixed $select The selection expressions.
+	 * @param string $alias The column alias used in the constructed query.
+	 *
+	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
+	 */
+	public function selectAlias($select, $alias) {
+
+		$this->queryBuilder->addSelect(
+			$this->helper->quoteColumnName($select) . ' AS ' . $this->helper->quoteColumnName($alias)
+		);
+
+		return $this;
+	}
+
 	/**
 	 * Adds an item that is to be returned in the query result.
 	 *
diff --git a/lib/public/db/querybuilder/iquerybuilder.php b/lib/public/db/querybuilder/iquerybuilder.php
index 3fc07af1a471bad034a0bf12b6690a363843d480..beb922b7feb10fa9d2488306d7a3e18568f08085 100644
--- a/lib/public/db/querybuilder/iquerybuilder.php
+++ b/lib/public/db/querybuilder/iquerybuilder.php
@@ -238,6 +238,24 @@ interface IQueryBuilder {
 	 */
 	public function select($select = null);
 
+	/**
+	 * Specifies an item that is to be returned with a different name in the query result.
+	 *
+	 * <code>
+	 *     $qb = $conn->getQueryBuilder()
+	 *         ->selectAlias('u.id', 'user_id')
+	 *         ->from('users', 'u')
+	 *         ->leftJoin('u', 'phonenumbers', 'p', 'u.id = p.user_id');
+	 * </code>
+	 *
+	 * @param mixed $select The selection expressions.
+	 * @param string $alias The column alias used in the constructed query.
+	 *
+	 * @return \OCP\DB\QueryBuilder\IQueryBuilder This QueryBuilder instance.
+	 * @since 8.2.1
+	 */
+	public function selectAlias($select, $alias);
+
 	/**
 	 * Adds an item that is to be returned in the query result.
 	 *
diff --git a/tests/lib/db/querybuilder/querybuildertest.php b/tests/lib/db/querybuilder/querybuildertest.php
index 75e62ba944ef1c4807578b272019a7e8a7d09d53..bbc45fc64f3efecbf5be070d24a2070a64018b56 100644
--- a/tests/lib/db/querybuilder/querybuildertest.php
+++ b/tests/lib/db/querybuilder/querybuildertest.php
@@ -159,24 +159,25 @@ class QueryBuilderTest extends \Test\TestCase {
 	}
 
 	public function dataSelect() {
+		$queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection());
 		return [
 			// select('column1')
-			[['column1'], ['`column1`'], '`column1`'],
+			[['configvalue'], ['configvalue' => '99']],
 
 			// select('column1', 'column2')
-			[['column1', 'column2'], ['`column1`', '`column2`'], '`column1`, `column2`'],
+			[['configvalue', 'configkey'], ['configvalue' => '99', 'configkey' => 'testing1']],
 
 			// select(['column1', 'column2'])
-			[[['column1', 'column2']], ['`column1`', '`column2`'], '`column1`, `column2`'],
+			[[['configvalue', 'configkey']], ['configvalue' => '99', 'configkey' => 'testing1']],
 
 			// select(new Literal('column1'))
-			[[new Literal('column1')], ['column1'], 'column1'],
+			[[$queryBuilder->expr()->literal('column1')], [], 'column1'],
 
 			// select('column1', 'column2')
-			[[new Literal('column1'), 'column2'], ['column1', '`column2`'], 'column1, `column2`'],
+			[[$queryBuilder->expr()->literal('column1'), 'configkey'], ['configkey' => 'testing1'], 'column1'],
 
 			// select(['column1', 'column2'])
-			[[[new Literal('column1'), 'column2']], ['column1', '`column2`'], 'column1, `column2`'],
+			[[[$queryBuilder->expr()->literal('column1'), 'configkey']], ['configkey' => 'testing1'], 'column1'],
 		];
 	}
 
@@ -184,45 +185,106 @@ class QueryBuilderTest extends \Test\TestCase {
 	 * @dataProvider dataSelect
 	 *
 	 * @param array $selectArguments
-	 * @param array $expectedQueryPart
-	 * @param string $expectedSelect
+	 * @param array $expected
+	 * @param string $expectedLiteral
 	 */
-	public function testSelect($selectArguments, $expectedQueryPart, $expectedSelect) {
+	public function testSelect($selectArguments, $expected, $expectedLiteral = '') {
+		$this->deleteTestingRows();
+		$this->createTestingRows();
+
 		call_user_func_array(
 			[$this->queryBuilder, 'select'],
 			$selectArguments
 		);
 
-		$this->assertSame(
-			$expectedQueryPart,
-			$this->queryBuilder->getQueryPart('select')
-		);
+		$this->queryBuilder->from('*PREFIX*appconfig')
+			->where($this->queryBuilder->expr()->eq(
+				'appid',
+				$this->queryBuilder->expr()->literal('testFirstResult')
+			))
+			->orderBy('configkey', 'ASC')
+			->setMaxResults(1);
 
-		$this->assertSame(
-			'SELECT ' . $expectedSelect . ' FROM ',
-			$this->queryBuilder->getSQL()
+		$query = $this->queryBuilder->execute();
+		$row = $query->fetch();
+		$query->closeCursor();
+
+		foreach ($expected as $key => $value) {
+			$this->assertArrayHasKey($key, $row);
+			$this->assertEquals($value, $row[$key]);
+			unset($row[$key]);
+		}
+
+		if ($expectedLiteral) {
+			$this->assertEquals([$expectedLiteral], array_values($row));
+		} else {
+			$this->assertEmpty($row);
+		}
+
+		$this->deleteTestingRows();
+	}
+
+	public function dataSelectAlias() {
+		$queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection());
+		return [
+			['configvalue', 'cv', ['cv' => '99']],
+			[$queryBuilder->expr()->literal('column1'), 'thing', ['thing' => 'column1']],
+		];
+	}
+
+	/**
+	 * @dataProvider dataSelectAlias
+	 *
+	 * @param mixed $select
+	 * @param array $alias
+	 * @param array $expected
+	 */
+	public function testSelectAlias($select, $alias, $expected) {
+		$this->deleteTestingRows();
+		$this->createTestingRows();
+
+		$this->queryBuilder->selectAlias($select, $alias);
+
+		$this->queryBuilder->from('*PREFIX*appconfig')
+			->where($this->queryBuilder->expr()->eq(
+				'appid',
+				$this->queryBuilder->expr()->literal('testFirstResult')
+			))
+			->orderBy('configkey', 'ASC')
+			->setMaxResults(1);
+
+		$query = $this->queryBuilder->execute();
+		$row = $query->fetch();
+		$query->closeCursor();
+
+		$this->assertEquals(
+			$expected,
+			$row
 		);
+
+		$this->deleteTestingRows();
 	}
 
 	public function dataAddSelect() {
+		$queryBuilder = new QueryBuilder(\OC::$server->getDatabaseConnection());
 		return [
 			// addSelect('column1')
-			[['column1'], ['`column`', '`column1`'], '`column`, `column1`'],
+			[['configvalue'], ['appid' => 'testFirstResult', 'configvalue' => '99']],
 
 			// addSelect('column1', 'column2')
-			[['column1', 'column2'], ['`column`', '`column1`', '`column2`'], '`column`, `column1`, `column2`'],
+			[['configvalue', 'configkey'], ['appid' => 'testFirstResult', 'configvalue' => '99', 'configkey' => 'testing1']],
 
 			// addSelect(['column1', 'column2'])
-			[[['column1', 'column2']], ['`column`', '`column1`', '`column2`'], '`column`, `column1`, `column2`'],
+			[[['configvalue', 'configkey']], ['appid' => 'testFirstResult', 'configvalue' => '99', 'configkey' => 'testing1']],
 
 			// select(new Literal('column1'))
-			[[new Literal('column1')], ['`column`', 'column1'], '`column`, column1'],
+			[[$queryBuilder->expr()->literal('column1')], ['appid' => 'testFirstResult'], 'column1'],
 
 			// select('column1', 'column2')
-			[[new Literal('column1'), 'column2'], ['`column`', 'column1', '`column2`'], '`column`, column1, `column2`'],
+			[[$queryBuilder->expr()->literal('column1'), 'configkey'], ['appid' => 'testFirstResult', 'configkey' => 'testing1'], 'column1'],
 
 			// select(['column1', 'column2'])
-			[[[new Literal('column1'), 'column2']], ['`column`', 'column1', '`column2`'], '`column`, column1, `column2`'],
+			[[[$queryBuilder->expr()->literal('column1'), 'configkey']], ['appid' => 'testFirstResult', 'configkey' => 'testing1'], 'column1'],
 		];
 	}
 
@@ -230,25 +292,45 @@ class QueryBuilderTest extends \Test\TestCase {
 	 * @dataProvider dataAddSelect
 	 *
 	 * @param array $selectArguments
-	 * @param array $expectedQueryPart
-	 * @param string $expectedSelect
+	 * @param array $expected
+	 * @param string $expectedLiteral
 	 */
-	public function testAddSelect($selectArguments, $expectedQueryPart, $expectedSelect) {
-		$this->queryBuilder->select('column');
+	public function testAddSelect($selectArguments, $expected, $expectedLiteral = '') {
+		$this->deleteTestingRows();
+		$this->createTestingRows();
+
+		$this->queryBuilder->select('appid');
+
 		call_user_func_array(
 			[$this->queryBuilder, 'addSelect'],
 			$selectArguments
 		);
 
-		$this->assertSame(
-			$expectedQueryPart,
-			$this->queryBuilder->getQueryPart('select')
-		);
+		$this->queryBuilder->from('*PREFIX*appconfig')
+			->where($this->queryBuilder->expr()->eq(
+				'appid',
+				$this->queryBuilder->expr()->literal('testFirstResult')
+			))
+			->orderBy('configkey', 'ASC')
+			->setMaxResults(1);
 
-		$this->assertSame(
-			'SELECT ' . $expectedSelect . ' FROM ',
-			$this->queryBuilder->getSQL()
-		);
+		$query = $this->queryBuilder->execute();
+		$row = $query->fetch();
+		$query->closeCursor();
+
+		foreach ($expected as $key => $value) {
+			$this->assertArrayHasKey($key, $row);
+			$this->assertEquals($value, $row[$key]);
+			unset($row[$key]);
+		}
+
+		if ($expectedLiteral) {
+			$this->assertEquals([$expectedLiteral], array_values($row));
+		} else {
+			$this->assertEmpty($row);
+		}
+
+		$this->deleteTestingRows();
 	}
 
 	public function dataDelete() {