PostgreSQL查询中的动态列

PostgreSQL查询中的动态列,sql,postgresql,pivot,Sql,Postgresql,Pivot,在我的PostgreSQL数据库中,我有以下模式: CREATE TABLE clients ( id integer NOT NULL, name character varying(255) ); CREATE TABLE services ( id integer NOT NULL, name character varying(255) NOT NULL ); CREATE TABLE client_services ( id integer

在我的PostgreSQL数据库中,我有以下模式:

CREATE TABLE clients (
    id integer NOT NULL,
    name character varying(255)
);

CREATE TABLE services (
    id integer NOT NULL,
    name character varying(255) NOT NULL
);

CREATE TABLE client_services (
    id integer NOT NULL,
    client_id integer NOT NULL,
    service_id integer NOT NULL
);


INSERT INTO clients(id, name)
VALUES (1, 'Client 1'), 
       (2, 'Client 2');

INSERT INTO services(id, name)
VALUES (1, 'Service 1'), 
       (2, 'Service 2');       

INSERT INTO client_services(id, client_id, service_id)
VALUES (1, 1, 1),
       (2, 1, 2),
       (3, 2, 2);          
我有以下疑问:

SELECT DISTINCT
    c.name,
    COUNT(cs.id) FILTER(WHERE s.name = 'Service 1') AS "Service 1",
    COUNT(cs.id) FILTER(WHERE s.name = 'Service 2') AS "Service 2"
FROM
    clients c
INNER JOIN
    client_services cs ON cs.client_id = c.id
INNER JOIN 
    services s ON s.id = cs.service_id
GROUP BY
    c.name; 
其中返回以下内容:

| name     | Service 1 | Service 2 |
| -------- | --------- | --------- |
| Client 1 | 1         | 1         |
| Client 2 | 0         | 1         |
问题是,若我决定向
services
表中添加另一个服务,我将需要更新我的查询。有没有办法使查询的这一部分成为动态的:

COUNT(cs.id) FILTER(WHERE s.name = 'Service 1') AS "Service 1",
COUNT(cs.id) FILTER(WHERE s.name = 'Service 2') AS "Service 2"
编辑:

我忘了添加链接do sql fiddle:


您应该在应用程序中进行这种格式化,SQL在这方面并不擅长。您究竟是如何(在哪里)使用该查询的结果的?如果您将其用于显示目的,聚合到键/值结构(例如JSONB)可能是更好的选择最终结果应该显示在哪里?仅查询或在应用程序中(web或其他)?为什么不简单地做如下操作:选择不同的c.id作为客户端id,c.name作为客户端id,s.id作为服务id,s.name作为服务名称,count(*)作为客户端服务计数,c加入客户端服务cs上的cs。客户端id=c.id加入服务s上的s.id=cs.service\U id按c.id分组,s.id;然后在显示表中使用结果?如果希望客户端\服务\计数显式为0,则需要执行内部联接服务和左联接客户端\服务。您尝试执行的实际上是具有动态列的透视表。这在SQL中是非常困难的。正如其他人所说,如果您在web应用程序中显示这一点,更好的方法是在代码的应用程序端执行这一逻辑。作为参考,这里有一个关于动态数据透视表的问题:如果您想在web应用程序中显示结果,那么JSON聚合是在SQL中更灵活的方式。您应该在应用程序中进行这种格式化,SQL并不擅长于此。您究竟是如何(在哪里)使用该查询的结果的?如果您将其用于显示目的,聚合到键/值结构(例如JSONB)可能是更好的选择最终结果应该显示在哪里?仅查询或在应用程序中(web或其他)?为什么不简单地做如下操作:选择不同的c.id作为客户端id,c.name作为客户端id,s.id作为服务id,s.name作为服务名称,count(*)作为客户端服务计数,c加入客户端服务cs上的cs。客户端id=c.id加入服务s上的s.id=cs.service\U id按c.id分组,s.id;然后在显示表中使用结果?如果希望客户端\服务\计数显式为0,则需要执行内部联接服务和左联接客户端\服务。您尝试执行的实际上是具有动态列的透视表。这在SQL中是非常困难的。正如其他人所说,如果您在web应用程序中显示这一点,更好的方法是在代码的应用程序端执行这一逻辑。作为参考,这里有一个关于动态数据透视表的问题:如果您想在web应用程序中显示结果,那么JSON聚合是在SQL中更灵活的方式。