在 Postgres 中将 COUNT 与聚合一起使用

Using COUNT with aggregate in Postgres

我运行下面的查询来检索我的数据:

SELECT
    e.id AS id, e.name AS name, e.description AS description,
    c.slug AS category,
    COUNT(t.id) AS sold,
    json_agg(json_build_object('id', b.id, 'title', b.title, 'description', b.description,'price', b.price, 'available', b.qty_available, 'qty_per_sale', b.qty_per_sale))::JSONB AS book,
    json_agg(json_build_object('id', s.id, 'startDate', s.start_date, 'endDate', s.end_date,'daysAhead', (s.start_date::DATE - NOW()::DATE), 'times', s.times))::JSONB as dates
FROM event e
    LEFT JOIN books b ON b.event_id = e.id
    LEFT JOIN shows s ON s.event_id = e.id
    LEFT JOIN category c ON e.category_id = c.id
    LEFT JOIN ticket t ON t.book_id = b.id
WHERE
    (status = 'PUBLISHED' OR status = 'PROMOTED')
    AND s.end_date >= DATE(NOW())
    AND e.is_private = FALSE
    AND s.id = t.show_id
    AND t.canceled = FALSE
GROUP BY  e.id,c.slug
ORDER BY  sold
LIMIT  30

这个查询工作正常。我得到事件级聚合 sold.

TABLE ticket (
    id SERIAL PRIMARY KEY,
    book_id SERIAL REFERENCES books(id),
    order_id SERIAL REFERENCES purchases(id),
    show_id SERIAL REFERENCES shows(id),
    showtime character varying(10) NOT NULL,
    canceled boolean DEFAULT false
);

我想在日期内向此报告添加另一个 sold 属性。目前,日期条目如下所示:

[
  {
    "id": 46,
    "times": [
      {
        "end": "13:00",
        "start": "12:00"
      }
    ],
    "endDate": "2022-02-27",
    "daysAhead": 308,
    "startDate": "2022-02-27"
  },
  {
    "id": 46,
    "times": [
      {
        "end": "13:00",
        "start": "12:00"
      }
    ],
    "endDate": "2022-02-27",
    "daysAhead": 308,
    "startDate": "2022-02-27"
  }
]

我想在等于 time.start 的门票放映时间上进行汇总,因此除了开始和结束之外,每个时间元素看起来都有这个新的 sold 属性。

我尝试使用 Postgres WITH 将当前查询变成一个集合,然后 JOIN ticket table 再次在其上,到目前为止没有太大成功。

基本上,我希望把时间分开,并在每个事件中添加一个 属性,如 COUNT(t.id),每个节目只过滤。

但是不允许嵌套聚合,COUNT()是一个。

有什么建议吗?

与其将当前查询变成 with 语句并再次加入票证,不如采用另一种方式更容易,即在 with 中使用票证 table ] 子句并将其加入当前查询。从你的描述中我不确定你想要输出的样子,但可能是这样的:

WITH ticket_summary as(
   select book_id, count(1) as ticket_count
   from ticket
   group by book_id
)
SELECT
    e.id AS id, e.name AS name, e.description AS description,
    c.slug AS category,
    COUNT(t.id) AS sold,
    json_agg(json_build_object('id', b.id, 'title', b.title, 'description', b.description,'price', b.price, 'available', b.qty_available, 'qty_per_sale', b.qty_per_sale, 'sales', ts.ticket_count))::JSONB AS book, --can now use in aggregate
    json_agg(json_build_object('id', s.id, 'startDate', s.start_date, 'endDate', s.end_date,'daysAhead', (s.start_date::DATE - NOW()::DATE), 'times', s.times))::JSONB as dates
FROM event e
    LEFT JOIN books b ON b.event_id = e.id
    LEFT JOIN shows s ON s.event_id = e.id
    LEFT JOIN category c ON e.category_id = c.id
    LEFT JOIN ticket t ON t.book_id = b.id
    --pull in summary data
    LEFT JOIN ticket_summary ts ON ts.book_id = b.id
WHERE
    (status = 'PUBLISHED' OR status = 'PROMOTED')
    AND s.end_date >= DATE(NOW())
    AND e.is_private = FALSE
    AND s.id = t.show_id
    AND t.canceled = FALSE
GROUP BY  e.id,c.slug
ORDER BY  sold
LIMIT  30