Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从分组依据中选择单个且仅单个行_Sql_Postgresql_Aggregate_Postgresql Performance - Fatal编程技术网

Sql 从分组依据中选择单个且仅单个行

Sql 从分组依据中选择单个且仅单个行,sql,postgresql,aggregate,postgresql-performance,Sql,Postgresql,Aggregate,Postgresql Performance,我有两个表:parcel和structure,它们之间有一对多关系:structure.parcel_id指向parcel.id 我想选择所有的单一结构。我目前的解决方案可行,但非常怪异: SELECT max(column_1), max(column_2), max(column_3), ... (twenty+ columns) FROM structure GROUP BY parcel_id HAVING count(structure.id) = 1; 因为structure.

我有两个表:parcel和structure,它们之间有一对多关系:structure.parcel_id指向parcel.id

我想选择所有的单一结构。我目前的解决方案可行,但非常怪异:

SELECT 
max(column_1),
max(column_2),
max(column_3),
...
(twenty+ columns)

FROM structure
GROUP BY parcel_id
HAVING count(structure.id) = 1;
因为structure.id是不可为null的,并且上面的HAVING子句,根据定义,每个组中只有一行。不幸的是,博士后没有意识到这一点,所以如果我说:

SELECT *    
FROM structure
GROUP BY parcel_id
HAVING count(structure.id) = 1;
然后我得到了关于需要对列使用聚合函数的预期错误。我使用任意的max函数来解决这个问题,但是这会让其他试图理解代码的人感到困惑,它迫使我显式地列出所有列,这意味着每当添加一列时,我都必须返回并编辑此代码。不幸的是,这种情况在我的环境中经常发生

我有另一种解决方案,它解决了我的大部分问题:

SELECT * FROM STRUCTURE
WHERE id IN (
    SELECT
        max(id) as id
    FROM structure
    GROUP by structure.parcel_id
    HAVING count(structure.id)  = 1
    );
但这显然给我的查询增加了不必要的缓慢,我希望避免这种情况,因为查询的频率和表的大小

与我所问的非常相似,但它会抓住每个组的第一行,而不是第一行也是唯一一行的单数组

有没有优雅的方法来解决这个问题

每个请求的示例数据:

结构表:

预期结果:

id | parcel_id | column_1 | column_2 | ...
------------------------------------------
3  |   537     |   ...    | ....     | ...
6  |   539     |   ...    | ....     | ...
7  |   540     |   ...    | ....     | ...
请注意,537、539和540是唯一不重复的地块id


两个表都有150万行和25列。

使用窗口函数怎么样

SELECT s.*    
FROM (SELECT s.*, COUNT(*) OVER (PARTITION BY parcel_id) as cnt
      FROM structure s
     ) s
WHERE cnt = 1;
但是,更有效的方法可能是:

select s.*
from structure s
where not exists (select 1
                  from structure s2
                  where s2.parcel_id = s.parcel_id and s2.id<> s.id
                 );

特别是,这可以利用structureparcel_id,id上的索引。

这应该快得多:

SELECT s.*
FROM  (
   SELECT parcel_id
   FROM   structure
   GROUP  BY 1
   HAVING count(*) = 1
   ) s1
JOIN structure s USING (parcel_id);
您所需要的只是地块id的索引

由于查询仅限于唯一的地块id,因此子查询中不需要涉及id。因此,我们可以从一个简单的索引中得到一个关于parcel_id的索引,并对连接使用相同的索引

连接应该比使用大的子选择时快一点。虽然它们在现代Postgres中的查询计划基本相同

count*比count快一点,因为只需要建立一行的存在

旁白:

在不存在的情况下,反半联接也应该很快。您只需要一个关于地块id的多列索引,id

这是针对SQL Server的。以下是一个与博士后更相关的问题:


请您发布一些有代表性的样本数据和期望的结果。因此,结构表有1.5M行。地块表中有多少行?有多少地块在结构表中只有一个对应行?换句话说,最终查询将返回多少行?我不太熟悉SQL,所以在评论中发布了我的建议。您可以使用自连接作为“选择S1.*从结构S1,结构S2中,其中S1.parcel\u id=S2.parcel\u id按S2分组。parcel\u id有计数S2.parcel\u id=1”您的第二种方法非常聪明!我喜欢它,但经过一些虽然相当粗糙的基准测试和查询计划分析后,它看起来会比我的古怪解决方案慢。我希望找到一个解决方案,至少在速度上能与之匹配。@inhubbell。你有合适的索引吗?我希望第二条消息在索引中会非常迅速。
SELECT s.*
FROM  (
   SELECT parcel_id
   FROM   structure
   GROUP  BY 1
   HAVING count(*) = 1
   ) s1
JOIN structure s USING (parcel_id);