PostgreSQL extract hour和group by的和值为0不';不显示结果

PostgreSQL extract hour和group by的和值为0不';不显示结果,sql,postgresql,Sql,Postgresql,我在Postgres中有这个SQL请求 SELECT CAST(extract(hour from CAST("public"."v_mdmeddialogues"."datecreation" AS timestamp)) AS integer) AS "datecreation", "public"."v_mdmeddialogues"."refspecialty"

我在Postgres中有这个SQL请求

SELECT CAST(extract(hour from
                    CAST("public"."v_mdmeddialogues"."datecreation" AS timestamp)) AS integer) AS "datecreation",
       "public"."v_mdmeddialogues"."refspecialty"                                              AS "refspecialty",
       "Refspecialty"."label"                                                                  AS "label",
       COALESCE(count(distinct "public"."v_mdmeddialogues"."iddialogue"), 0)                   AS "count",
       COALESCE(sum("public"."v_mdmeddialogues"."timespent"), 0)                               AS "heures"
FROM "public"."v_mdmeddialogues"
         LEFT JOIN "public"."v_mdiddoctors" "Refuser" ON "public"."v_mdmeddialogues"."refuser" = "Refuser"."iduser"
         LEFT JOIN "public"."v_mdparamspecialties" "Refspecialty"
                   ON "public"."v_mdmeddialogues"."refspecialty" = "Refspecialty"."idspecialty"
WHERE (date_trunc('month', CAST("public"."v_mdmeddialogues"."datecreation" AS timestamp)) BETWEEN date_trunc('month',
                                                                                                             CAST(
                                                                                                                     (CAST(now() AS timestamp) + (INTERVAL '-3 month')) AS timestamp)) AND date_trunc('month', CAST(now() AS timestamp)) AND
       "Refspecialty"."label" = 'Dermatologie' AND
       "public"."v_mdmeddialogues"."codedialogueaction" in ('RESPONSE', 'TRANSFER'))
  AND extract('dow' FROM "public"."v_mdmeddialogues"."datecreation") IN (0, 6)
GROUP BY CAST(extract(hour from CAST("public"."v_mdmeddialogues"."datecreation" AS timestamp)) AS integer),
         "public"."v_mdmeddialogues"."refspecialty", "Refspecialty"."label"
ORDER BY CAST(extract(hour from CAST("public"."v_mdmeddialogues"."datecreation" AS timestamp)) AS integer) ASC,
         "public"."v_mdmeddialogues"."refspecialty" ASC, "Refspecialty"."label" ASC;
问题是在凌晨4点到5点之间没有“发生”的值,因此结果显示:

我的桌子是:

    create table mdmeddialogues
(
    iddialogue         varchar(255),
    codedialoguetype   varchar(255),
    refdialogueroot    bigint,
    codedialogueaction varchar(255),
    refuser            varchar(255),
    refspecialty       varchar(255),
    datecreation       timestamp,
    refoperator        varchar(255),
    source             varchar(255),
    timespent          bigint,
    datelastupdate     timestamp
);

create table mdparamspecialties
(
    idspecialty    varchar(255),
    code           varchar(255),
    label          varchar(255),
    active         bit,
    exclusive      bit,
    valid          bit,
    datelastupdate timestamp
);
如您所见,结果跳过了
datecreation
中的值4。如何在
count
heures
中用空值(0)显示此行


感谢您的帮助

首先,这与您的问题是分开的,但是在
v_mdMedDialogs
中添加一个别名并进行一点格式化确实可以在提高查询的可读性方面提供很大帮助。此外,您还有很多不必要的强制转换,例如,将时间戳强制转换为时间戳。我假设
datecreation
是一个文本字段,在这种情况下,我保留了转换,但如果是日期/时间,那么转换也是不必要的,甚至有点误导。最后,在我看来,过度引用是一种干扰。您唯一需要引号的时间是当引号位于表的DDL中时,我强烈反对在几乎每个实例中使用引号

无论如何,使用上述观察结果快速重构原始查询可能如下所示(为了保持简单,我将public.v_mdMedDialogs别名为“md”):

免责声明:我可能把一两件事弄糟了,但希望你们能看到这更易读,更容易理解

现在谈谈你的问题。如果您有一个已知的数据集作为输出,那么您可以生成该数据集,然后将其留在我们的查询中。在这种情况下,看起来您需要一个保证的0-23。为此,您可以使用
generate_series(0,23)
来创建这些,然后将其左连接关闭:

SELECT
   gs.datecreation,
   md.refspecialty AS refspecialty,
   Refspecialty.label AS label,
   COALESCE(count(distinct md.iddialogue), 0) AS count,
   COALESCE(sum(md.timespent), 0)  AS heures
FROM
   generate_series (0, 23) gs (datecreation)
   left join mdmeddialogues md on
     gs.datecreation = extract (hour from md.datecreation) and 
     date_trunc('month', md.datecreation) BETWEEN
        date_trunc('month', current_timestamp) - INTERVAL '3 month' AND 
        date_trunc('month', current_timestamp) AND
     md.codedialogueaction in ('RESPONSE', 'TRANSFER') and
     extract('dow' FROM md.datecreation) IN (0, 6)
   LEFT JOIN mdiddoctors Refuser ON 
     md.refuser = Refuser.iduser
   LEFT JOIN mdparamspecialties Refspecialty on
     md.refspecialty = Refspecialty.idspecialty and
     Refspecialty.label = 'Dermatologie'
GROUP BY
  gs.datecreation, md.refspecialty, Refspecialty.label
ORDER BY
  gs.datecreation ASC, md.refspecialty ASC, Refspecialty.label ASC;

如果您希望
refspeciality
label
值也显示出来,那就另当别论了。因为这两个值中的一个是在where子句中硬编码的,所以您可以将其添加到合并中。

Hello@Hambone我按照您所说的那样清理了请求并添加了“generate series”,但结果仍然与以前一样。我认为左连接是问题所在,因为这一行LEFT JOIN public.v_mdmedDialogs as md on extract(hour from md.datecreation::timestamp)=gs有0个结果您可以发布表的DDL吗?我在第一个问题上发布了它们是的,的确。。。这就是我在回答之前不测试东西的情况。因此,基于DDL,我删除了两个额外的不必要的强制转换(时间戳到时间戳),并修复了一些语法错误,其中我未能一致地应用别名。在第二条SQL语句中,我犯了一个典型的错误,将where条件放在where子句中,从而使左连接等效于内部连接。试试上面的方法,看看是否有帮助。没有数据,不可能确定,但我认为它在方向上非常接近你想要的。这就是结果:它不是完美的,但足够好。非常感谢您与您的问题相关,但是:您应该真正避免那些可怕的引用标识符。他们的麻烦远比他们值得的多。是的,是@Hambone指出的
SELECT
   gs.datecreation,
   md.refspecialty AS refspecialty,
   Refspecialty.label AS label,
   COALESCE(count(distinct md.iddialogue), 0) AS count,
   COALESCE(sum(md.timespent), 0)  AS heures
FROM
   generate_series (0, 23) gs (datecreation)
   left join mdmeddialogues md on
     gs.datecreation = extract (hour from md.datecreation) and 
     date_trunc('month', md.datecreation) BETWEEN
        date_trunc('month', current_timestamp) - INTERVAL '3 month' AND 
        date_trunc('month', current_timestamp) AND
     md.codedialogueaction in ('RESPONSE', 'TRANSFER') and
     extract('dow' FROM md.datecreation) IN (0, 6)
   LEFT JOIN mdiddoctors Refuser ON 
     md.refuser = Refuser.iduser
   LEFT JOIN mdparamspecialties Refspecialty on
     md.refspecialty = Refspecialty.idspecialty and
     Refspecialty.label = 'Dermatologie'
GROUP BY
  gs.datecreation, md.refspecialty, Refspecialty.label
ORDER BY
  gs.datecreation ASC, md.refspecialty ASC, Refspecialty.label ASC;