【问题标题】:LEFT JOIN with condition that is variable具有可变条件的 LEFT JOIN
【发布时间】:2014-03-13 21:20:46
【问题描述】:

我正在创建 PostgreSQL 视图。 (部分问题在这里解决了PostgreSQL - count data as zero if it is null (when where clause is used)):

我遇到的问题是我需要在 LEFT JOIN 中使用条件作为变量,因为我不知道在该查询(视图)的“运行时”之前将使用哪种日期进行过滤。 OpenERP中使用了这种视图。它使用字段来过滤来自主 SELECT 列的结果。例如,当您在视图中看到opp.name as name 时,在 OpenERP 中您可以使用此列进行过滤。这种方法可以,但我需要查看所有 LEFT 表结果。我的意思是,如果我使用任何过滤器,它仍应显示右表中的零(空)值,如下例所示。但是在 OpenERP 中,如果您使用 SELECT 中使用的列中的过滤器,那么它会像普通 JOIN 一样过滤,结果只会是两列中都存在的值(或者不是 LEFT JOIN)。

那么有没有办法以某种方式描述变量,而不是在 LEFT JOIN 中使用特定日期作为条件(现在在示例中您会看到这个 AND log.create_date <= '2014-01-29 08:49:03',我需要类似 AND log.create_date <= some_variable 的东西)。代码如下:

CREATE TABLE crm_lead(
  id integer PRIMARY KEY,
  name char(64) NOT NULL

);

CREATE TABLE crm_lead_stage_log(
  id integer PRIMARY KEY,
  opportunity_id integer references crm_lead(id),
  stage_id integer,
  create_date timestamp
);

INSERT INTO crm_lead VALUES (1, 'opp1');
INSERT INTO crm_lead VALUES (2, 'opp2');
INSERT INTO crm_lead VALUES (3, 'opp3');

INSERT INTO crm_lead_stage_log VALUES (1, 1, 1, '2014-01-28 08:49:03');
INSERT INTO crm_lead_stage_log VALUES (2, 1, 2, '2014-01-29 08:49:03');
INSERT INTO crm_lead_stage_log VALUES (3, 2, 1, '2014-02-02 08:49:03');
INSERT INTO crm_lead_stage_log VALUES (4, 2, 1, '2014-02-03 08:49:03');

CREATE VIEW report_crm_lead_stage_log as

SELECT opp.name as name,
       count(log.stage_id) as stage_count,
       to_char(log.create_date, 'YYYY-MM-DD') as stage_changed_day
FROM crm_lead as opp 
  LEFT JOIN crm_lead_stage_log as log 
         ON opp.id = log.opportunity_id
        AND log.create_date <= '2014-01-29 08:49:03'
GROUP BY name, log.create_date
ORDER BY name;

输出是这样的:

NAME            STAGE_COUNT STAGE_CHANGED_DAY
opp1    1           2014-01-28
opp1            1           2014-01-29
opp2            0           (null)
opp3            0           (null)

您也可以在此处查看架构 (http://sqlfiddle.com/#!12/de78e/1)

【问题讨论】:

  • 您可以使用返回记录集的函数来实现此目的。是否有可能用函数替换您的视图?
  • @Houari 我读到可以这样做,但不鼓励这样做。但如果没有其他选择,也许您可​​以发布此建议,以便我查看并尝试使其发挥作用。

标签: sql postgresql


【解决方案1】:

这是一个函数示例:

--Creating a type returned by the function:
CREATE TYPE my_type AS (name CHARACTER(64), stage_count BIGINT, stage_changed_day TEXT);

--And the function
CREATE OR REPLACE FUNCTION report_crm_lead_stage_log(date_filter timestamp without time zone)
  RETURNS SETOF my_type AS
$BODY$declare 
begin
return query (SELECT opp.name as name,
       count(log.stage_id) as stage_count,
       to_char(log.create_date, 'YYYY-MM-DD') as stage_changed_day
FROM crm_lead as opp 
  LEFT JOIN crm_lead_stage_log as log 
         ON opp.id = log.opportunity_id
            AND log.create_date <= date_filter
GROUP BY name, log.create_date
ORDER BY name);

end;$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;

Source

【讨论】:

    猜你喜欢
    • 2020-08-24
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    • 2012-08-22
    • 2023-04-06
    • 1970-01-01
    • 2014-07-30
    相关资源
    最近更新 更多