【问题标题】:Joining two tables with aggregates使用聚合连接两个表
【发布时间】:2013-07-05 21:17:01
【问题描述】:

我有两个如下所述的表:

CREATE TABLE categories
(
  id integer NOT NULL,
  category integer NOT NULL,
  name text,
  CONSTRAINT kjhfskfew PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);

CREATE TABLE products_
(
  id integer NOT NULL,
  date date,
  id_employee integer,
  CONSTRAINT grh PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);

现在我必须做报告,其中需要以下信息: categories.category, categories.name (所有这些,所以 string_agg 是可以的) - 可以很多分配给一个类别和 products_.id_employee -> 但不是像上面那样用逗号和类别名称,而是分配了最新日期的那个(在这里是我的问题);

我已经尝试过如下构造:

SELECT
  DISTINCT ON (category ) category,
  string_agg(name, ','),
  (SELECT
     id_employee
   FROM products_
   WHERE date = (SELECT
                   max(date)
                 FROM products_
                 WHERE id IN (SELECT
                                id
                              FROM categories
                              WHERE id = c.id)))
FROM categories c
ORDER BY category;

但是 PostgreSQL 说子查询返回到很多行... 请帮忙!

示例插入:

INSERT INTO categories(
            id, category, name)
    VALUES (1,22,'car'),(2,22,'bike'),(3,22,'boat'),(4,33,'soap'),(5,44,'chicken');

INSERT INTO products_(
            id, date, id_employee)
    VALUES (1,'2009-11-09',11),(2,'2010-09-09',2),(3,'2013-01-01',4),(5,'2014-09-01',90);

好的,我已经解决了这个问题。 这个很好用:

WITH max_date AS (
    SELECT
      category,
      max(date)             AS date,
      string_agg(name, ',') AS names
    FROM test.products_
      JOIN test.categories c
      USING (id)
    GROUP BY c.category
)
SELECT
  max(id_employee) AS id_employee,
  md.category,
  names
FROM test.products_ p
  LEFT JOIN max_date md
  USING (date)
  LEFT JOIN test.categories
  USING (category)
WHERE p.date = md.date AND p.id IN (SELECT
                                      id
                                    FROM test.categories
                                    WHERE category = md.category)
GROUP BY category, names;

【问题讨论】:

  • 如果您有机会为示例数据行添加一些 INSERT 命令以及您希望从该示例数据中看到的结果摘要,这将有助于使此类事情成为更容易回答。
  • 当然,我刚刚更新了我的帖子。
  • 你想达到什么目的不清楚。你能解释一下吗?
  • 我需要按类别对行进行分组。对于每个类别(本例中有 3 个 - 22,33 和 44)我需要显示类别表中的名称,因此类别 22 将是:“汽车”、“自行车”和“船”。第三件事是 id_employee 分配给 products_ 表中的 id -> 并且 ihis id_employee 应该是 max(date) - 所以从类别中分配给类别的最大日期。按 22 类别应该是 4,因为日期 '2013-01-01' 是最大的。
  • 我失败了,所以看看类别和产品是如何相关的。 categories 表中的idcategory 列有什么区别?

标签: sql join postgresql-9.2


【解决方案1】:

似乎id 被用于连接这两个表,这对我来说似乎很奇怪。

无论如何,类别名称的基本查询是:

SELECT c.category, string_agg(c.name, ','),
FROM categories c
group by c.category;

问题是:如何获取最新的名称?此方法使用row_number() 函数:

SELECT c.category, string_agg(c.name, ','), cp.id_employee
FROM categories c left outer join
     (select c.category, c.name, p.id_employee,
             row_number() over (partition by c.category order by date desc) as seqnum
      from categories c left outer join
           products_ p
           on c.id = p.id
     ) cp
     on cp.category = c.category and
        cp.seqnum = 1
group by c.category, cp.id_employee;

【讨论】:

  • "好像id被用来连接两个表,我觉得很奇怪。" - 为什么会这样?
  • @Borys 。 . .首先id,当用作列名时,通常是指表中自动递增的主键列。而且,这似乎就是它在这里的使用方式。这些表是“平行的”,因为主键之间存在 1-1 关系;但是它们的名称(“类别”和“产品”)暗示了非常不同的实体。我希望categories 中的主键是CategoryId(或类似的东西)。并且products_ 有一个引用它的外键。
  • 是的,现在我明白你的意思了。但是表的名称已更改,并且此结构用于完全不同的目的,这就是为什么它看起来有点奇怪;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-13
  • 1970-01-01
  • 1970-01-01
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多