哪里有 SQL 子查询

Where with SQL subquery

我有以下查询:

SELECT 
`id`, `firstName`, `lastName`, `nickName`, `email`, 
`verificationCode`, `roleId`, `profileImageId`, `statusId`, `createdAt`, 
(SELECT COUNT(*) FROM RecipeStores WHERE RecipeStores.userId = User.id) AS `countStoredRecipes`, 
(SELECT COUNT(*) FROM RecipeFavorites WHERE RecipeFavorites.userId = User.id) AS `countLikedRecipes`, 
(SELECT COUNT(*) FROM Recipes WHERE Recipes.createdById = User.id) AS `countCreatedRecipes` 
FROM `Users` AS `User` WHERE `User`.`countStoredRecipes` >= 2;

然而,它不起作用。我想通过子查询的结果进行过滤。

我知道子查询不能再作为一个列来工作,所以我希望有其他方法可以做到这一点。

MySQL 实现了标准 SQL 的扩展,允许您在 HAVING 子句中引用别名:

SELECT 
    `id`, `firstName`, `lastName`, `nickName`, `email`, 
    `verificationCode`, `roleId`, `profileImageId`, `statusId`, `createdAt`, 
    (SELECT COUNT(*) FROM RecipeStores rs WHERE rs.userId = u.id) AS `countStoredRecipes`, 
    (SELECT COUNT(*) FROM RecipeFavorites rf WHERE rf.userId = u.id) AS `countLikedRecipes`, 
    (SELECT COUNT(*) FROM Recipes r WHERE r.createdById = u.id) AS `countCreatedRecipes` 
FROM `Users` u
HAVING `User`.`countStoredRecipes` >= 2;

我不是这种技术的忠实粉丝:这确实是定制的 MySQL 语法,在任何其他数据库中都不会 运行。

一个更标准的选项是将现有查询转换为子查询,并在外部范围内进行过滤:

SELECT *
FROM (
    SELECT 
        `id`, `firstName`, `lastName`, `nickName`, `email`, 
        `verificationCode`, `roleId`, `profileImageId`, `statusId`, `createdAt`, 
        (SELECT COUNT(*) FROM RecipeStores rs WHERE rs.userId = u.id) AS `countStoredRecipes`, 
        (SELECT COUNT(*) FROM RecipeFavorites rf WHERE rf.userId = u.id) AS `countLikedRecipes`, 
        (SELECT COUNT(*) FROM Recipes r WHERE r.createdById = u.id) AS `countCreatedRecipes` 
    FROM `Users` u
) t
WHERE `countStoredRecipes` >= 2;

在 MySQL 的最新版本中,您可以使用横向连接:

SELECT 
    `id`, `firstName`, `lastName`, `nickName`, `email`, 
    `verificationCode`, `roleId`, `profileImageId`, `statusId`, `createdAt`, 
    rs.*, rf.*, r.* 
    () AS  
FROM `Users` u
INNER JOIN LATERAL (
    SELECT COUNT(*) AS `countStoredRecipes` 
    FROM RecipeStores rs 
    WHERE rs.userId = u.id
) rs ON rs.`countStoredRecipes`>= 2
LEFT JOIN LATERAL (
    SELECT COUNT(*) AS `countLikedRecipes` 
    FROM RecipeFavorites rf 
    WHERE rf.userId = u.id
) rf ON true
LEFT JOIN LATERAL (
    SELECT COUNT(*) AS `countCreatedRecipes` 
    FROM Recipes r 
    WHERE r.createdById = u.id
) r ON true