如何在SQL中使用子查询?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在SQL中使用子查询?相关的知识,希望对你有一定的参考价值。

我有4张桌子: Travelers (TravelerID,FirstName,LastName) Guides(GuideID,FirstName,LastName) Locations(LocationID,LocationName) Trips(TravelerID,GuideID,LocationID,Stars,StartDate,ReturnDate)

我想按指南返回他引导最多旅行者人数的位置名称。

我试图使用此子查询,但它不起作用:

SELECT G.FirstName,L.LocationName,count(distinct(TravelerID))as number_of_travelers_per_guide 
FROM Guides AS G 
LEFT JOIN Trips AS T USING (GuideID) 
LEFT JOIN Locations AS L USING (LocationID)
GROUP BY G.FirstName,L.LocationName 
HAVING max((SELECT T1.number_of_travelers_per_guide 
            FROM Trips AS T1 
            WHERE T.GuideID=T1.GuideID));

我将不胜感激任何帮助

答案

这是mysql的真正痛苦,因为pre v 8版本既没有CTE也没有窗口函数。一种方法使用变量:

SELECT gl.*
FROM (SELECT gl.*,
             (@rn := if(@g = gl.FirstName, @rn + 1,
                        if(@g := gl.FirstName, 1, 1)
                       )
             ) as rn
      FROM (SELECT G.FirstName, L.LocationName, count(distinct TravelerID) as number_of_travelers_per_guide 
            FROM Guides G LEFT JOIN
                 Trips T
                 USING (GuideID) LEFT JOIN
                 Locations L
                 USING (LocationID)
            GROUP BY G.FirstName, L.LocationName 
            ORDER BY G.FirstName, number_of_travelers_per_guide DESC
           ) gl CROSS JOIN
           (SELECT @g := '', @rn := -1) params
      ) gl
WHERE rn = 1;

我不会强调理解MySQL中的变量。相反,了解row_number()rank()dense_rank() - 这些是在几乎所有数据库中解决问题的正确方法。

另一答案

尝试使用完整的功能而不是alis

SELECT G.FirstName,L.LocationName, count(distinct T.TravelerID ) as number_of_travelers_per_guide 
FROM Guides AS G 
LEFT JOIN Trips AS T USING (GuideID) 
LEFT JOIN Locations AS L USING (LocationID)
GROUP BY G.FirstName,L.LocationName 
HAVING count(distinct TravelerID ) = ( 
            select max(my_count) from (SELECT count(distinct T.TravelerID) my_count
            FROM Guides AS G 
            LEFT JOIN Trips AS T USING (GuideID) 
            LEFT JOIN Locations AS L USING (LocationID)
            GROUP BY G.FirstName, L.LocationName ) my_t );
另一答案

如果不能使用CTE和分析函数,我想你会看到类似下面的内容。然而,如果指南具有两个相等排名的位置,则存在危险,将为该指南而不是仅一个返回两行或更多行。

SELECT
    G.FirstName
    ,L.LocationName
    ,guide_stats.traveler_count

FROM
    (
        SELECT
            GuideID
            ,LocationID
            ,COUNT(DISTINCT TravelerID) AS traveler_count

        FROM Trips
        GROUP BY GuideID, LocationID

    ) AS guide_stats

INNER JOIN
    (
        SELECT 
            guide_stats_for_max.GuideID
            ,MAX(guide_stats_for_max.traveler_count) AS max_traveler_count

        FROM
        (
            SELECT
                GuideID
                ,LocationID
                ,COUNT(DISTINCT TravelerID) AS traveler_count

            FROM Trips
            GROUP BY GuideID, LocationID

        ) AS guide_stats_for_max

        GROUP BY GuideID

    ) AS guide_max
    ON (guide_stats.GuideID = guide_max.GuideID)
    AND (guide_stats.traveler_count = guide_max.max_traveler_count)

LEFT JOIN Guides    AS G USING (guide_stats.GuideID)
LEFT JOIN Locations AS L USING (guide_stats.LocationID)

注意我已编写此代码而未进行测试 - 请原谅小错误。

以上是关于如何在SQL中使用子查询?的主要内容,如果未能解决你的问题,请参考以下文章

使用 with as 优化SQL

sql [SQL查询片段]用于在命令行或通过R和其他工具使用SQL的快速代码段#tags:sql,R,text processing,命令li

如何在 SQL 中组合两个查询? (子查询)

如何在 SQL 子查询中使用 WHERE EXISTS?

如何在 sql 中使用子查询创建约束?

如何在不破坏SQL逻辑的情况下将JOINS转换为子查询