当前位置: 首页 > 面试题库 >

带有SUM的Postgres LEFT JOIN,缺少记录

傅长恨
2023-03-14
问题内容

我正在尝试获取相关表中某些记录类型的计数。我正在使用左联接。

因此,我有一个查询不太正确,并且正在返回正确的结果。正确的结果查询具有较高的执行成本。如果可以纠正结果,我想使用第一种方法。(请参阅http://sqlfiddle.com/#!15/7c20b/5/2)

CREATE TABLE people(
  id SERIAL,
  name varchar not null
);

CREATE TABLE pets(
  id SERIAL,
  name varchar not null, 
  kind varchar not null,
  alive boolean not null default false,
  person_id integer not null
);

INSERT INTO people(name) VALUES
('Chad'),
('Buck'); --can't keep pets alive

INSERT INTO pets(name, alive, kind, person_id) VALUES
('doggio', true, 'dog', 1),
('dog master flash', true, 'dog', 1),
('catio', true, 'cat', 1),
('lucky', false, 'cat', 2);

我的目标是与所有这些人和他们活着的宠物种类一起归还一张桌子:

| ID | ALIVE_DOGS_COUNT | ALIVE_CATS_COUNT |
|----|------------------|------------------|
|  1 |                2 |                1 |
|  2 |                0 |                0 |

我使这个例子变得微不足道了。在我们的生产应用程序中(不是真正的宠物),每人大约有100,000只死狗和猫。我知道搞砸了,但是这个例子更容易传递;)我希望在计数之前过滤掉所有“死”的东西。我现在在生产中查询速度较慢(从上面的sqlfiddle中查询),但希望使LEFT
JOIN版本能够正常工作。


问题答案:

如果您获取 所有或大多数行, 通常最快:

SELECT pp.id
     , COALESCE(pt.a_dog_ct, 0) AS alive_dogs_count
     , COALESCE(pt.a_cat_ct, 0) AS alive_cats_count
FROM   people pp
LEFT   JOIN (
   SELECT person_id
        , count(kind = 'dog' OR NULL) AS a_dog_ct
        , count(kind = 'cat' OR NULL) AS a_cat_ct
   FROM   pets
   WHERE  alive
   GROUP  BY 1
   ) pt ON pt.person_id = pp.id;

此处的索引无关紧要,全表扫描将是最快的。 除非 活着的宠物 很少见 ,否则
部分索引
应该有所帮助。喜欢:

CREATE INDEX pets_alive_idx ON pets (person_id, kind) WHERE alive;

我包括了查询所需的所有列,(person_id, kind)以允许仅索引扫描。

SQL提琴。

通常对于 较小的子集或单行 最快:

SELECT pp.id
     , count(kind = 'dog' OR NULL) AS alive_dogs_count
     , count(kind = 'cat' OR NULL) AS alive_cats_count
FROM   people pp
LEFT   JOIN pets pt ON pt.person_id = pp.id
                   AND pt.alive
WHERE  <some condition to retrieve a small subset>
GROUP  BY 1;

您至少应该pets.person_id为此指定一个索引(或上面的部分索引),并且可能还要更多,具体取决于WHERE条件。



 类似资料:
  • 问题内容: 我有一个二维布尔数组’poorSignal’,需要编写一个返回网格的方法,如果数组上的某个点为true,则显示X,如果为false,则显示O。这是我的代码: 当我编译时,它在方法的最后一行给出了“丢失的返回语句”。我也不确定在打印数组时’return“ \ n”是否可以添加新行。 这是一个分配问题,所以我不能直接打印它,也不能仅打印布尔值-它必须是产生网格的方法。 问题答案: 编译器无

  • 我试图编写一个调用REST服务的web应用程序。REST服务需要用户的OAuth令牌。使用用户的用户名和密码,我可以获得一个SAML令牌(下面的第一个断言),OAuth STS可以使用该令牌向我发出一个有效的OAuth令牌。因为我在一个web应用程序中,所以我更喜欢使用ActAs SAML令牌,而不是提示输入已经通过域(SSO)身份验证的用户的用户名和密码。当我将ADFS 2.0配置为发出ActA

  • 我们有一个Maven多模块项目,由父级(HelloWorld)和不同的子级(HelloWorldServices和HelloWorldPresentation)组成,并使用Jenkins进行构建。 运行成功测试后的错误是

  • 我正在尝试通过使用spring-cloud d-gcp-starter-log将SpringBootApplication(微服务)与StackdriverLogging集成。我能够在GCP中看到日志,但在日志中traceId和SPANId丢失。为此,我也尝试使用Spring-cloud d-sleuth,但由于我在我的微服务中使用apache kafka,因此侦探无法正常工作。有人能帮我吗我如何

  • 问题内容: 我想intigrate 并进入我的Maven的webapp尝试与地狱世界。不幸的是,Jersey和Grizzly的依赖关系很麻烦,无法正常工作。 我尝试删除该文件夹,因为我认为该文件夹可能已损坏而没有帮助。我添加了其他依赖项,例如jsoup,效果很好。实际上,它在日志中是从存储库下载jersey- server的,因此它不是网络问题。 有谁能够帮我?我真的被卡住了! 我的Eclipse

  • 问题内容: 我有一张桌子,桌子之间有一对多的关系。每个记录可以有来自同一张表的n个孩子。例如 给定一个ID,我想递归选择所有文件夹记录的SUM(SIZE)。目标数据库是MySql 5,但是如果它的通用性足以在Oracle和MS- SQL中运行,那将是很好的选择。 我不知道树有多深,可能是1级,可能是50级(或更多) 问题答案: 这可能会有些帮助:http : //mikehillyer.com/a