我知道我必须写SUM两次,如果我想在HAVING子句中使用它(否则使用派生表):
SELECT id,
sum(hours) AS totalhours
FROM mytable
GROUP BY id
HAVING sum(hours) > 50;
Run Code Online (Sandbox Code Playgroud)
我现在的问题是,这是否是次优的。作为程序员,这个查询看起来 DB 会计算两次总和。是这样,还是我应该依赖数据库引擎将为我做的优化?
更新:可比查询的解释:
postgres=> explain select sum(counttodo) from orderline group by orderlineid having sum(counttodo) > 100;
QUERY PLAN
--------------------------------------------------------------------
HashAggregate (cost=1.31..1.54 rows=18 width=8)
Filter: (sum(counttodo) > 100)
-> Seq Scan on orderline (cost=0.00..1.18 rows=18 width=8)
(3 rows)
Run Code Online (Sandbox Code Playgroud) 我正在尝试在格式为 PostgreSQL 查询中返回一个文本字段
'stringOne' || string_agg(field, ',') || 'stringTwo'
Run Code Online (Sandbox Code Playgroud)
对于 group 子句中的某些元素, wherefield始终为 null。我想要并期望stringOnestringTwo在这种情况下结束,但我得到NULL.
为什么会这样,我如何完成我想要做的事情?
假设我有桌子
foo bar
+----+--------+ +----+-------+--------------+
| id | name | | id | fooid | baz |
+----+--------+ +----+-------+--------------+
| 1 | FooOne | | 1 | 1 | FooOneBazOne |
| 2 | FooTwo | | 2 | 1 | FooTwoBazTwo |
+----+--------+ +----+-------+--------------+
Run Code Online (Sandbox Code Playgroud)
我运行查询
SELECT
foo.name AS foo,
'Bazzes: ' || string_agg(bar.baz, ', ') AS bazzes …Run Code Online (Sandbox Code Playgroud) 有没有办法索引以下查询?
SELECT run_id, MAX ( frame ) , MAX ( time ) FROM run.frames_stat GROUP BY run_id;
Run Code Online (Sandbox Code Playgroud)
我尝试在frameand上创建排序(非复合)索引time,并在 上创建索引run_id,但查询规划器不使用它们。
杂项信息:
frames_stat表有 4200 万行架构:
CREATE TABLE run.frame_stat (
id bigint NOT NULL,
run_id bigint NOT NULL,
frame bigint NOT NULL,
heap_size bigint NOT NULL,
"time" timestamp without time zone NOT NULL,
CONSTRAINT frame_stat_pkey PRIMARY KEY (id)
)
Run Code Online (Sandbox Code Playgroud)
解释分析:
HashAggregate (cost=1086240.000..1086242.800 …Run Code Online (Sandbox Code Playgroud) 我很抱歉这个模糊的标题,但我根本不知道用什么合适的词来描述这个。
我有这个查询将一堆列转换为一个可以正常工作的对象:
SELECT row_to_json(t)
FROM (
SELECT type, properties, geometry FROM "bgbCargoMinardJSON"
) t
Run Code Online (Sandbox Code Playgroud)
但是,我想将属于某个类别的对象分组到一个数组中。该类别由我的表中名为“cargoProductId”的第四列定义。该数组应将“cargoProductId”的值作为键。所以:
SELECT row_to_json(t)
FROM (
SELECT type, properties, geometry FROM "bgbCargoMinardJSON"
) t
Run Code Online (Sandbox Code Playgroud)
所以我在过去的 1 1/2 小时左右一直在努力解决这个问题。我真的不知道如何做到这一点。这就是我现在所拥有的:
SELECT array_agg(row_to_json(t))
FROM (
SELECT type, properties, geometry FROM "bgbCargoMinardJSON"
) t) FROM "bgbCargoMinardJSON" GROUP BY "carProductId"
Run Code Online (Sandbox Code Playgroud) 是否可以在 Postgres 中创建某种分组链?假设我有以下图表:
CREATE TABLE foo AS
SELECT row_number() OVER () AS id, *
FROM ( VALUES
( 'X', 'D', 'G', 'P' ),
( 'F', 'D', 'L', 'M' ),
( 'X', 'N', 'R', 'S' ),
( 'Y', 'I', 'W', NULL ),
( 'U', 'Z', 'E', NULL )
) AS f(a,b,c,d);
id | a | b | c | d
------------------
1 | X | D | G | P
2 | F | D | L | M
3 | …Run Code Online (Sandbox Code Playgroud) 我正在重写不再提取所有必需数据的查询。我的问题是关于我从未见过的实践,也没有在 StackExchange 上找到任何专门解决该问题的问题。
我知道该HAVING语句的重点是在聚合上引入条件,就像WHERE在单个行上引入条件一样。但是,我在这段代码中看到的内容HAVING被用来代替WHERE带有聚合的查询。中的条件HAVING不适用于聚合,而是应用于非聚合列。
例如:
SELECT id, filedate, SUM(amount)
FROM Sales
GROUP BY id, filedate
HAVING id = 123 AND filedate = '1/1/2018'
Run Code Online (Sandbox Code Playgroud)
与之相反:
SELECT id, filedate, SUM(amount)
FROM Sales
WHERE id = 123 AND filedate = '1/1/2018'
GROUP BY id, filedate
Run Code Online (Sandbox Code Playgroud)
此策略是否有性能影响或其他优点/缺点?
我还没有尝试过自己运行诊断程序,这不是优先事项,我必须在自己的时间进行。但是,如果对此没有明确的答案,我想我可以。
我关心的是优化器如何看待这个查询。它是聚合所有数据,然后根据HAVING子句限制结果集,还是意识到它可以将具有条件应用于单个行,因为它们专门引用非聚合列?
编辑:对于我的示例查询和我正在重写的实际 SQL,计划是相同的,但查询具有相似的复杂性,而且我的知识还不够丰富,无法从相同的计划中得出结论。
performance sql-server aggregate t-sql group-by query-performance
我正在使用 Postgres,它强制执行 SELECT...GROUP BY 中的所有列必须出现在 GROUP BY 子句中或在聚合函数中使用的约束。
假设我正在为人们的汽车建模,我想算出一个人的姓名、牌照号码以及他们拥有的汽车数量。这是我作为SQL Fiddle 的示例。
我会有以下架构:
CREATE TABLE person(
id integer PRIMARY KEY,
name text
);
CREATE TABLE license(
person_id integer REFERENCES person(id),
expiry_date date
);
CREATE TABLE car(
owner_id integer REFERENCES person(id),
registration_number TEXT
);
Run Code Online (Sandbox Code Playgroud)
这是查询:
SELECT person.name, person.id, license.expiry_date, COUNT(car) FROM person
JOIN license ON license.person_id = person.id
JOIN car ON car.owner_id = person.id
WHERE person.name = 'Charles Bannerman'
GROUP BY person.id;
Run Code Online (Sandbox Code Playgroud)
我知道,因为我自己的业务逻辑,一个人只能有一个license,所以当我加入这个人的时候,即使是GROUP BY'd,我应该可以找到他们的license number。但是,因为它不是 GROUP …
使用 Postgres:
SELECT users."name" AS "name"
, array_to_json(array_agg(sites)) as sites
FROM remodel.users AS users
JOIN remodel.user_sites AS user_sites
ON users.id=user_sites.user
JOIN remodel.sites AS sites
ON sites.id=user_sites.site
GROUP BY "users".id
;
Run Code Online (Sandbox Code Playgroud)
目前生产
SELECT users."name" AS "name"
, array_to_json(array_agg(sites)) as sites
FROM remodel.users AS users
JOIN remodel.user_sites AS user_sites
ON users.id=user_sites.user
JOIN remodel.sites AS sites
ON sites.id=user_sites.site
GROUP BY "users".id
;
Run Code Online (Sandbox Code Playgroud)
但是我不想在 JSON 输出中有“id”字段。
将站点选择更改为
array_to_json(array_agg(row(sites."name", sites.created))) as sites
Run Code Online (Sandbox Code Playgroud)
导致字段失去名称
"Toby";"[{"id":1,"name":"Village","created":"2015-08-10T15:22:36.622298"},
{"id":2,"name":"Manor","created":"2015-08-10T15:22:43.614551"}]"
"Amy";"[{"id":3,"name":"Park","created":"2015-08-10T15:22:48.810872"}]"
"Anne";"[{"id":2,"name":"Manor","created":"2015-08-10T15:22:43.614551"},
{"id":1,"name":"Village","created":"2015-08-10T15:22:36.622298"},
{"id":3,"name":"Park","created":"2015-08-10T15:22:48.810872"}]"
Run Code Online (Sandbox Code Playgroud)
并尝试(这将是一个可怕的)子选择
, array_to_json(array_agg((SELECT "name", created FROM …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个查询,当连接表 B 中的列包含表 A 中单个匹配行的多个不同值时,该查询从表 A 中返回一行。(A -> B 是 1 -> 多关系。)我构建了在上下文中演示这一点的 SQL 小提琴:http : //sqlfiddle.com/#!6/83952/1
在这个小提琴中,表格的design列perf_ticket_type对于每个ticket_type具有相同的 都应该是相同的perf_id,但我试图只选择它没有的实例。因此,对于perf_id3,design我当前使用的查询返回了不止一个唯一值。
我想我的结果是两列performance的表只对perf_id3的基础上的多重价值design为perf_id所加入的表。
过去我一直对 GROUP BY 的理解感到沮丧,所以我不确定我是否可以在这里做一些不同的事情来获得我想要的结果。此刻,我想我可以选择什么我都在拨弄到一个临时表,然后做另一个选择上是有GROUP BY perf_id HAVING COUNT(*) > 1得到我想要的东西(按其中列包含在一个以上的记录相同的数据选择行)但这似乎是一个额外的步骤。
我需要显示产品在过去 4 次生产中的平均重量。除了示例之外,我不知道如何最好地描述它:让我们想象一下,我有下表按创建日期列出了产品,以及当天产品的平均重量:
+---------+---------+--------+
| Product | Date | Weight |
+---------+---------+--------+
| 900000 | Jan 1 | 20.0 |
| 900000 | March 3 | 12.2 |
| 900000 | July 6 | 15.0 |
| 900000 | July 7 | 14.0 |
| 900000 | Aug 6 | 3.0 |
| 800000 | June 2 | 14.0 |
| 800000 | June 3 | 12.0 |
+---------+---------+--------+
Run Code Online (Sandbox Code Playgroud)
我正在寻找的最终结果是添加一个列,其中包含产品运行的最后 4 个日期的平均重量,因此如下所示:
+---------+---------+--------+----------------+
| Product | Date | Weight | …Run Code Online (Sandbox Code Playgroud) aggregate ×10
postgresql ×7
group-by ×3
sql-server ×3
t-sql ×2
alias ×1
concat ×1
index ×1
index-tuning ×1
join ×1
json ×1
null ×1
performance ×1
row ×1