SQL查询:迭代表中的值并在子查询中使用它们

时间:2015-09-22 20:48:41

标签: sql postgresql join subquery qsqlquery

我有一个包含一些值的简单SQL表,例如:

id | value    (table 'values')
----------
0  | 4
1  | 7
2  | 9

我想迭代这些值,并在如下的查询中使用它们:

SELECT value[0], x1
FROM (some subquery where value[0] is used)

UNION

SELECT value[1], x2
FROM (some subquery where value[1] is used) 

...
etc

为了获得这样的结果集:

4 | x1
7 | x2
9 | x3

它必须在SQL中,因为它实际上代表数据库视图。当然真正的查询要复杂得多,但我试图在尽可能保持本质的同时简化问题。

我认为我必须从中选择并加入子查询,但由于该值应该在子查询中使用,我将失去如何实现这一点。

编辑:我过分简化了我的问题;实际上我想从子查询中获得2行,而不仅仅是一行。

编辑2:正如我所建议的那样,我发布了真实的查询。我简化了一下以使其更清晰,但它是一个有效的查询,问题就在那里。请注意,我已经硬编码了值' 2'在这个查询中两次。我想用不同表中的值替换它,在上面的示例表中,我希望将此查询的组合结果的结果集以4,7和9作为值而不是当前硬编码的2。

SELECT x.fantasycoach_id, SUM(round_points)
FROM (
    SELECT DISTINCT fc.id AS fantasycoach_id,
        ffv.formation_id AS formation_id,
        fpc.round_sequence AS round_sequence,
        round_points,
        fpc.fantasyplayer_id
    FROM fantasyworld_FantasyCoach AS fc

    LEFT JOIN fantasyworld_fantasyformation AS ff ON ff.id = (
            SELECT MAX(fantasyworld_fantasyformationvalidity.formation_id)
            FROM fantasyworld_fantasyformationvalidity
            LEFT JOIN realworld_round AS _rr ON _rr.id = round_id
            LEFT JOIN fantasyworld_fantasyformation AS _ff ON _ff.id = formation_id
            WHERE is_valid = TRUE
                AND _ff.coach_id = fc.id
                AND _rr.sequence <= 2 /* HARDCODED USE OF VALUE */
            )
    LEFT JOIN fantasyworld_FantasyFormationPlayer AS ffp 
    ON ffp.formation_id = ff.id

    LEFT JOIN dbcache_fantasyplayercache AS fpc 
    ON ffp.player_id = fpc.fantasyplayer_id
    AND fpc.round_sequence = 2 /* HARDCODED USE OF VALUE */

    LEFT JOIN fantasyworld_fantasyformationvalidity AS ffv 
    ON ffv.formation_id = ff.id
) x
GROUP BY fantasycoach_id

编辑3:我正在使用PostgreSQL。

3 个答案:

答案 0 :(得分:3)

SQL与表一起使用,基本上涉及集合操作。没有明确的迭代,通常不需要任何迭代。特别是,您所描述的最简单的实现方式是:

SELECT value, (some subquery where value is used) AS x
FROM values

但请注意,相关的子查询,例如查询性能非常困难。根据您尝试执行的操作的详细信息,可以围绕简单连接,不相关的子查询或类似的,性能更好的替代方案来构建它。

<强>更新

鉴于问题的更新表明子查询预计会为表values中的每个值产生多行,与示例结果相反,似乎更好的方法是重写子查询作为主要查询。如果它还没有这样做(可能即使它确实如此)那么它会将表values作为另一个基表连接。

更新2:

鉴于现在提供的真实查询,这就是表values中的值可以合并到其中的方式:

SELECT x.fantasycoach_id, SUM(round_points) FROM
(
    SELECT DISTINCT
        fc.id AS fantasycoach_id, 
        ffv.formation_id AS formation_id, 
        fpc.round_sequence AS round_sequence,
        round_points,
        fpc.fantasyplayer_id

    FROM fantasyworld_FantasyCoach AS fc
    -- one row for each combination of coach and value:
    CROSS JOIN values

    LEFT JOIN fantasyworld_fantasyformation AS ff
    ON ff.id = (
        SELECT MAX(fantasyworld_fantasyformationvalidity.formation_id)
        FROM fantasyworld_fantasyformationvalidity

        LEFT JOIN realworld_round AS _rr
        ON _rr.id = round_id

        LEFT JOIN fantasyworld_fantasyformation AS _ff
        ON _ff.id = formation_id

        WHERE is_valid = TRUE
        AND _ff.coach_id = fc.id

        -- use the value obtained from values:
        AND _rr.sequence <= values.value
    )

    LEFT JOIN fantasyworld_FantasyFormationPlayer AS ffp
    ON ffp.formation_id = ff.id

    LEFT JOIN dbcache_fantasyplayercache AS fpc
    ON ffp.player_id = fpc.fantasyplayer_id

    -- use the value obtained from values again:
    AND fpc.round_sequence = values.value

    LEFT JOIN fantasyworld_fantasyformationvalidity AS ffv
    ON ffv.formation_id = ff.id
) x
GROUP BY fantasycoach_id

特别注意构成两个表的叉积的CROSS JOIN;这与没有任何连接谓词的INNER JOIN相同,如果需要,可以这样写。

总体查询可能至少有点简化,但我不这样做,因为它是一个工作示例而不是实际的生产查询,因此不清楚其他更改会转化为实际应用程序。

答案 1 :(得分:3)

在示例中,我创建了两个表。看看外表如何在内部选择中使用别名?

SQL Fiddle Demo

SELECT T.[value], (SELECT [property] FROM Table2 P WHERE P.[value] = T.[value])
FROM Table1 T 

这是一种更好的表现方式

SELECT T.[value], P.[property]
FROM Table1 T 
INNER JOIN Table2 p
   on P.[value] = T.[value];

Table 2可以是QUERY而不是真实的表

第三选项

使用cte计算您的值,然后重新加入主表。这样,您可以将子查询逻辑与最终查询分开。

WITH cte AS (
    SELECT 
        T.[value],
        T.[value] * T.[value] as property
    FROM Table1 T 
)
SELECT T.[value], C.[property]
FROM Table1 T 
INNER JOIN cte C
   on T.[value] = C.[value];

答案 2 :(得分:0)

将计算提取到SELECT子句中调用的函数并对结果集的每一行执行可能会有所帮助

以下是SQL Server CREATE FUNCTION的文档。它可能类似于您正在使用的任何数据库系统,如果没有,您可以轻松地使用谷歌。

以下是创建函数并在查询中使用它的示例:

CREATE FUNCTION DoComputation(@parameter1 int)
RETURNS int
AS
BEGIN
   -- Do some calculations here and return the function result.
   -- This example returns the value of @parameter1 squared.
   -- You can add additional parameters to the function definition if needed

   DECLARE @Result int
   SET @Result = @parameter1 * @parameter1

   RETURN @Result
END

以下是在查询中使用上述示例函数的示例。

SELECT v.value, DoComputation(v.value) as ComputedValue
FROM [Values] v
ORDER BY value