我有一个SQL查询,我需要在其中获取子查询的输出并多次使用它。我现有的查询有效,但前提是每次需要时都重复子查询。不幸的是,子查询很复杂,并且需要时间来执行 - 这意味着多次迭代确实会使整个事情变慢。
我已经读过你可以使用“WITH”语句将子查询输出分配给变量,以便重用该变量。但是我遇到的问题是在子查询中,我需要引用主查询中的值。并且似乎如果我在主查询SELECT之前使用WITH - 则不能识别这些引用。我会给你一个简化的例子:
WITH
DateX AS
(
SELECT
MAX(TableSub.Date)
FROM
TableA TableSub
WHERE
TableSub.ID = TableMain.ID
AND TableSub.Event = 'AnotherEvent'
AND TableSub.Date BETWEEN '01-Jan-2015' AND '31-Dec-2015'
)
SELECT
TableMain.ID
FROM
TableA TableMain
WHERE
TableMain.Event = 'MainEvent'
AND TableMain.Date >= DateX
AND (
SELECT
TableSub2.ID
FROM
TableA TableSub2
WHERE
TableSub2.ID = TableMain.ID
TableSub2.Event = 'ThirdEvent'
AND TableSub2.Date <= DateX
) IS NULL
我希望这很清楚。它是我所拥有的简化版本,但您可以看到DateX在多个位置使用:在主查询中,在子查询中。但问题是当DateX由WITH定义时,我需要将ID链接回主查询的ID。它不起作用......
如果有任何建议,我将不胜感激。我做错了吗?有办法,还是只是不可能?如果是这样,那么我应该完全使用另一种方法吗?感谢。
答案 0 :(得分:1)
更好的方法:
SELECT ID
FROM (
SELECT ID,
"Date",
Event,
LAST_VALUE( CASE Event WHEN 'AnotherEvent' THEN "Date" END IGNORE NULLS )
OVER ( PARTITION BY ID ORDER BY "Date"
ROWS BETWEEN UNBOUNDED PRECEEDING AND UNBOUNDED FOLLOWING
) AS another_date,
FIRST_VALUE( CASE Event WHEN 'ThirdEvent' THEN "Date" END IGNORE NULLS )
OVER ( PARTITION BY ID ORDER BY "Date"
ROWS BETWEEN UNBOUNDED PRECEEDING AND UNBOUNDED FOLLOWING
) AS third_date
FROM TableA
WHERE Event IN ( 'MainEvent', 'ThirdEvent' )
OR ( Event = 'AnotherEvent' AND EXTRACT( YEAR FROM "Date" ) = 2015 )
)
WHERE Event = 'MainEvent'
AND "Date" >= another_date
AND ( third_date IS NULL OR third_date > another_date );
答案 1 :(得分:0)
您需要在ID列上加入您的DateX CTE。类似的东西:
WITH
DateX AS
(
SELECT
TableSub.ID,
MAX(TableSub.Date) AS MaxDate
FROM
TableA TableSub
WHERE
AND TableSub.Event = 'AnotherEvent'
AND TableSub.Date >= DATE '2015-01-01'
AND TableSub.Date < DATE '2016-01-01'
GROUP BY
TableSub.ID
)
SELECT
TableMain.ID
FROM
TableA TableMain
JOIN
DateX
ON
DateX.ID = TableMain.ID
WHERE
TableMain.Event = 'MainEvent'
AND TableMain.Date >= DateX.MaxDate
AND (
SELECT
TableSub2.ID
FROM
TableA TableSub2
JOIN
DateX
ON
DateX.ID = TableSub2.ID
WHERE
TableSub2.ID = TableMain.ID
TableSub2.Event = 'ThirdEvent'
AND TableSub2.Date <= DateX.MaxDate
) IS NULL
CTE还需要聚合的列别名;当你需要加入ID时,你需要包含它并按其分组。
最后一个子查询看起来很奇怪;如果您没有找到记录,则可能需要NOT EXISTS
而不是IS NULL
。也许你真正的查询是使用聚合,但即便这样也可能更快。
这仍然可能不是最好的方法,但从你的例子中很难说清楚。三次击中同一张桌子可能会不必要地花费很多。