查询五张表,包括两张相互关联的联结表,形成View

Query five tables including two inter-related junction tables to form View

我有三个tables (surveypoint, sample, fldwrk_images):一个surveypoint可以有很多或没有样本,surveypoint和sample都可以有很多或没有图像,surveypoint都可以和样本链接到两个单独的结点 table,因为图像可以是一个或多个 samples/surveypoints。这两个多对多关系由连接 table fldwrk_images.

的两个连接点 table(svypnt_fldwrk_image_junc 和 sample_fldwrk_image_junc)形成

我正在尝试创建一个视图,使每一行都包含测量点信息、与测量点相关的示例信息(如果有)和图像信息(如果有)。由于图像来自交界处 tables,我希望在测量点和样本上有重复的信息,这很好,但我希望视图在 image_id.

上是不同的

下面是我尝试的查询,当 运行 永远持续下去时,很明显它是有缺陷的,我不知道该怎么做。

CREATE OR REPLACE VIEW query_fldwrk_images_by_surveypoint_and_sample AS 
SELECT DISTINCT ON (fi1.fldwrk_image_id) svypnt_fldwrk_image_junc.svypnt_fldwrk_image_junc_id,
fi1.image_path,
fi1.image_name,
fi1.iptc_caption,
fi1.iptc_keywords,
srpnt1.surveypoint_name,
fi1.fldwrk_image_id,
sam1.sample_name
FROM surveypoint as srpnt1
LEFT JOIN sample sam2 ON srpnt1.surveypoint_id = sam2.surveypoint_id,
svypnt_fldwrk_image_junc
LEFT JOIN fldwrk_image fi1 ON svypnt_fldwrk_image_junc.fldwrk_image_id = fi1.fldwrk_image_id
LEFT JOIN surveypoint srpnt2 ON svypnt_fldwrk_image_junc.surveypoint_id = srpnt2.surveypoint_id,
sample_fldwrk_image_junc
LEFT JOIN fldwrk_image fi2 ON sample_fldwrk_image_junc.fldwrk_image_id = fi2.fldwrk_image_id
LEFT JOIN sample sam1 ON sample_fldwrk_image_junc.sample_id = sam1.sample_id;

交叉连接

问题是这个

FROM surveypoint as srpnt1
LEFT JOIN sample sam2 ON srpnt1.surveypoint_id = sam2.surveypoint_id

不以任何方式加入此

svypnt_fldwrk_image_junc
LEFT JOIN fldwrk_image fi1 ON svypnt_fldwrk_image_junc.fldwrk_image_id = fi1.fldwrk_image_id
LEFT JOIN surveypoint srpnt2 ON svypnt_fldwrk_image_junc.surveypoint_id = srpnt2.surveypoint_id

并且都没有加入这个

sample_fldwrk_image_junc
LEFT JOIN fldwrk_image fi2 ON sample_fldwrk_image_junc.fldwrk_image_id = fi2.fldwrk_image_id
LEFT JOIN sample sam1 ON sample_fldwrk_image_junc.sample_id = sam1.sample_id

(请注意,table 别名在 surveypointsample 上是不同的。)这将创建一个 CROSS JOIN,从而产生三组 tables。如果每个组有 1,000 条记录,则视图将有 1,000,000,000 条记录,这需要 一些 时间来准备。

更改 samplesurveypoint 的别名并重新安排连接顺序将使您的视图快速准备就绪。

区分开

您注意到您希望视图是 DISTINCT ONsurveypoint 关联的 image_id。这里有几点需要考虑:

  • 除非您包含 ORDER BY 子句,否则保留在视图中的记录是不确定的,甚至达到针对视图的单独查询可以显示不同结果的程度。
  • 显然,一个 surveypoint 可以有很多图像,一个图像可以与一个 surveypoint 及其任何一个 sample 相关联。美好的。但是一张图片可以关联多个 surveypoint 吗?这听起来不太合逻辑。

改写你的叙述(并添加一些根据你在问题中的查询似乎有意义的猜测),你似乎想要这个(伪SQL):

CREATE VIEW query_fldwrk_images_by_surveypoint_and_sample AS
  SELECT surveypoint_info, sample_info, image_info
  WHERE image_info IS ANY image_info LINKED TO svy_pnt
  OR ELSE ANY image_info LINKED TO ANY smpl LINKED TO svy_pnt NOT USED IN OTHER RECORDS

由于两条路径上的多对多关系以及 DISTINCT ON 和 image_id 的要求,这不能以确定性的方式在简单查询中完成。简而言之,问题是您必须创建 surveypoint-sample-image 的组合并跟踪您分配的图像位置,如果您在某处遇到 NULL 可能会回溯(例如,您可以有一个 surveypoint 没有图像 linked,所以你使用第一个可用的图像 sample。如果任何其他样本只有该图像 linked,它'将在没有有效图像的情况下出现(因为 DISTINCT ON 子句),而其他示例中可能有 "extra" 个图像。

您应该放宽 DISTINCT ON 要求,使此视图相对简单。这种放松可以是以下形式: 给所有测量点及其样本和测量点的图像;如果图像是NULL,则使用样本点的任何图像。您最终可能会得到来自不同样本的相同图像,但至少您会有自己的观点。

我认为这可能有效的唯一方法是颠倒逻辑:不是 link 将图像用于测量点和样本,link 后者用于图像,但是你'将遇到与多对多冲突相同的问题(即哪个测量点或样本分配给哪个图像)。递归 CTE 会完成艰苦的工作,但解决冲突仍然非常困难。

(我正在回答我自己的问题以引出 replies/comments 我的新数据库结构:我不确定这是否符合礼节...)

根据 Patrick 提供的第一个答案,由于我的数据库是结构化的,所以我无法查询它来提取我需要的信息。为了解决这个问题,我重组了数据库,从两个连接三个 table 的连接 table 到一个连接三个 table 的连接 table,新的连接 table 有一个 junction_pk、一个 image_id、一个 surveypoint_id 和一个 sample_id。由于一些测量点没有相关样本,在新交汇点 table 中有一些行没有 sample_id 数据。

为了提取我需要的所有信息,我在调查点上使用 select distinct on junction_id 创建了一个视图,首先使用 sample_id is null 然后在 [=28 上使用 union =] 不为空(这似乎是必需的,否则没有关联样本的调查点上的数据显示为空,因为无法说 sample_id 彼此相关)。

新结构似乎可以工作并且不会在我需要的视图中产生错误的连接(该视图基于另一个查询 - query.1 - 它首先查询六个 tables 以汇集所需的信息与图像相关联)。

我的问题是:这种联结 table 是否链接了数据库中的三个 table 良好实践:这会导致我不知道的问题吗?我创建视图的方式是使用 union 方法 appropriate/efficient?

查询是:

CREATE OR REPLACE VIEW query_surv_sam_images_irll14 AS 
     SELECT DISTINCT ON (junc1.svy_sam_image_junc_id) fi1.iptc_caption,
        query1.surveypoint_name,
        query1.sample_name,
        query1.material_name,
        query1.surv_formation_name,
        query1.surv_newcode,
        query1.samp_formation_name,
        query1.samp_newcode,
        query1.surveypoint_type_name,
        query1.surveypoint_descrp_brief,
        query1.surveypoint_description,
        query1.survey_date,
        query1.sample_type_name,
        query1.geochemical,
        query1.outcrop_grp_name,
        query1.outcrop_grp_descrp,
        query1.locality_name,
        query1.area_name,
        query1.waterbasin_name,
        query1.townland_name,
        query1.county,
        query1.country_name,
        junc1.svy_sam_image_junc_id,
        junc1.surveypoint_id,
        query1.surv_id,
        junc1.sample_id,
        query1.samp_id,
        fi1.image_name,
        fi1.image_path,
        fi1.geom
       FROM svy_sam_image_junc junc1
  JOIN fldwrk_image fi1 ON fi1.fldwrk_image_id = junc1.fldwrk_image_id
   LEFT JOIN query_srpnts_samples_irll14 query1 ON query1.surv_id = junc1.surveypoint_id
  WHERE junc1.sample_id IS NULL
UNION
     SELECT DISTINCT ON (junc1.svy_sam_image_junc_id) fi1.iptc_caption,
        query1.surveypoint_name,
        query1.sample_name,
        query1.material_name,
        query1.surv_formation_name,
        query1.surv_newcode,
        query1.samp_formation_name,
        query1.samp_newcode,
        query1.surveypoint_type_name,
        query1.surveypoint_descrp_brief,
        query1.surveypoint_description,
        query1.survey_date,
        query1.sample_type_name,
        query1.geochemical,
        query1.outcrop_grp_name,
        query1.outcrop_grp_descrp,
        query1.locality_name,
        query1.area_name,
        query1.waterbasin_name,
        query1.townland_name,
        query1.county,
        query1.country_name,
        junc1.svy_sam_image_junc_id,
        junc1.surveypoint_id,
        query1.surv_id,
        junc1.sample_id,
        query1.samp_id,
        fi1.image_name,
        fi1.image_path,
        fi1.geom
       FROM svy_sam_image_junc junc1
  JOIN fldwrk_image fi1 ON fi1.fldwrk_image_id = junc1.fldwrk_image_id
   LEFT JOIN query_srpnts_samples_irll14 query1 ON query1.samp_id = junc1.sample_id
  WHERE junc1.sample_id IS NOT NULL
  ORDER BY 2, 3, 1, 28;