SQL 在不重复 Where 的情况下在子查询中聚合
SQL Aggregate In Subquery Without Duplicating Where
所以下面的查询工作得很好,但没有找到一种方法来不在子查询和外部查询中复制 where 子句:
SELECT * FROM table WHERE --Cannot change this as it is hardcoded in ArcGIS layer definition, only can access WHERE
objectid IN (
SELECT objectid
FROM table a
RIGHT JOIN (
SELECT id, MIN(seq) as seq, --zone
FROM table b
WHERE zone IN ( 'ZONE2', 'ZONE3', 'ZONE4') GROUP BY id) c
ON a.id = c.id
AND a.seq = c.seq
--AND a.zone = c.zone
WHERE zone IN ( 'ZONE2', 'ZONE3', 'ZONE4')
)
我基本上想做一些像注释掉的部分这样的事情,它允许删除外部重复的 where 子句...但这当然行不通,因为没有分组依据。
- 不能在区域上使用 MIN 或 MAX,因为它们不能保证根据相应的序列号按字母顺序排列
- 不能按区域分组,因为那样会更改返回的 MIN(seq)
- 不能仅在外部查询中执行 WHERE,因为子查询无法获得正确的 MIN(seq)
- 不能仅在内部查询中执行 WHERE,因为其他区域中可能存在重复的序列号
我们在 WHERE 子句中有大约 15 种不同的区域,它们会随着时间慢慢改变。所以只是尽量减少重复,这可能有助于将它们关闭的长期可靠性。
非常感谢您的任何想法和帮助!
您可以使用相关子查询:
SELECT *
FROM table WHERE --Cannot change this as it is hardcoded in ArcGIS layer definition, only can access
WHERE objectid IN (SELECT a.objectid
FROM table a
WHERE a.seq = (SELECT min(seq)
FROM table b
WHERE b.zone = a.zone AND a.id = c.id
) AND
a.zone IN ( 'ZONE2', 'ZONE3', 'ZONE4')
);
您是否看过使用常见的 table 表达式 (CTE)
CTE 有点像可重用的子查询。
SELECT *
FROM table
WHERE --Cannot change this as it is hardcoded in ArcGIS layer definition, only can access
objectid IN (
SELECT objectid
FROM (
SELECT objectid,
seq,
MIN( seq ) OVER ( PARTITION BY id /*, zone */ ) AS min_seq
FROM table
WHERE zone IN ( 'ZONE2', 'ZONE3', 'ZONE4')
)
WHERE seq = min_seq
)
根据 Darrel 关于使用 CTE 的建议,我发现可以在外部查询中使用 WITH 子句。我一直认为它们只能在开始时使用。这是有效的代码:
SELECT * FROM table WHERE --Cannot change this as it is hardcoded in ArcGIS layer definition, only can access WHERE
objectid IN (
with filtered_zones as (
select objectid , id, zone, seq
from table
where zone in ( 'ZONE2', 'ZONE3', 'ZONE4'))
SELECT objectid
FROM filtered_zones a
JOIN (
SELECT id, MIN(seq) as seq
FROM filtered_zones b
GROUP BY id) c
ON a.id = c.id
AND a.seq = c.seq)
所以下面的查询工作得很好,但没有找到一种方法来不在子查询和外部查询中复制 where 子句:
SELECT * FROM table WHERE --Cannot change this as it is hardcoded in ArcGIS layer definition, only can access WHERE
objectid IN (
SELECT objectid
FROM table a
RIGHT JOIN (
SELECT id, MIN(seq) as seq, --zone
FROM table b
WHERE zone IN ( 'ZONE2', 'ZONE3', 'ZONE4') GROUP BY id) c
ON a.id = c.id
AND a.seq = c.seq
--AND a.zone = c.zone
WHERE zone IN ( 'ZONE2', 'ZONE3', 'ZONE4')
)
我基本上想做一些像注释掉的部分这样的事情,它允许删除外部重复的 where 子句...但这当然行不通,因为没有分组依据。
- 不能在区域上使用 MIN 或 MAX,因为它们不能保证根据相应的序列号按字母顺序排列
- 不能按区域分组,因为那样会更改返回的 MIN(seq)
- 不能仅在外部查询中执行 WHERE,因为子查询无法获得正确的 MIN(seq)
- 不能仅在内部查询中执行 WHERE,因为其他区域中可能存在重复的序列号
我们在 WHERE 子句中有大约 15 种不同的区域,它们会随着时间慢慢改变。所以只是尽量减少重复,这可能有助于将它们关闭的长期可靠性。
非常感谢您的任何想法和帮助!
您可以使用相关子查询:
SELECT *
FROM table WHERE --Cannot change this as it is hardcoded in ArcGIS layer definition, only can access
WHERE objectid IN (SELECT a.objectid
FROM table a
WHERE a.seq = (SELECT min(seq)
FROM table b
WHERE b.zone = a.zone AND a.id = c.id
) AND
a.zone IN ( 'ZONE2', 'ZONE3', 'ZONE4')
);
您是否看过使用常见的 table 表达式 (CTE)
CTE 有点像可重用的子查询。
SELECT *
FROM table
WHERE --Cannot change this as it is hardcoded in ArcGIS layer definition, only can access
objectid IN (
SELECT objectid
FROM (
SELECT objectid,
seq,
MIN( seq ) OVER ( PARTITION BY id /*, zone */ ) AS min_seq
FROM table
WHERE zone IN ( 'ZONE2', 'ZONE3', 'ZONE4')
)
WHERE seq = min_seq
)
根据 Darrel 关于使用 CTE 的建议,我发现可以在外部查询中使用 WITH 子句。我一直认为它们只能在开始时使用。这是有效的代码:
SELECT * FROM table WHERE --Cannot change this as it is hardcoded in ArcGIS layer definition, only can access WHERE
objectid IN (
with filtered_zones as (
select objectid , id, zone, seq
from table
where zone in ( 'ZONE2', 'ZONE3', 'ZONE4'))
SELECT objectid
FROM filtered_zones a
JOIN (
SELECT id, MIN(seq) as seq
FROM filtered_zones b
GROUP BY id) c
ON a.id = c.id
AND a.seq = c.seq)