左连接 count() 并在 table 内单独显示匹配项

Left join with count() and show matches separately within table

我数了不同日期和地区的鸟类。有些鸟有一个跟踪 ID。 这给了我一个 table 和这个 header。 t1:

SPECIES | AGE | BIRD_TRACKING_ID | AREA | DATE_1
------------------------------------------------
        |     |                  |      |

然后我们观察了鸟类,并记录了它们降落的树木。每棵树都有一个唯一的 ID。一只鸟本可以拜访过 none,一只鸟或几棵树。这给了我 table t2 这个 header:

TREE |DESCR  |TREE_ID |BIRD_ID
------------------------------
     |       |        |      


CREATE TABLE birds (
    SPECIES varchar(255),
    AGE varchar(255),
    BIRD_TRACKING_ID varchar(255),
    AREA varchar(255),
    DATE_1 date
);

INSERT INTO birds (SPECIES, AGE, BIRD_TRACKING_ID, AREA, DATE_1)
VALUES ('eagle',    'ad',  null,      'A03', '2021-06-02'),
       ('merl',     'ad', 'B_mer_01', 'A03', '2021-07-01'),
       ('owl',      'jv',  null,      'A04', '2021-06-11'),
       ('penguin',  'jv', 'B_pen_21', 'A04', '2021-07-01'),
       ('eagle',    'juv', null,      'A03', '2021-06-15'),
       ('eagle',    'ad', 'B_eag_16', 'A02', '2021-06-02'),
       ('merl',     'ad',  null,      'A03', '2021-08-01'),
       ('owl',      'jv', 'B_owl_01', 'A02', '2021-02-01'),
       ('penguin',  'jv', 'B_pen_23', 'A04', '2021-04-17'),
       ('penguin',  'jv',  null,      'A01', '2021-07-15'),
       ('eagle',    'ad', 'B_eag_23', 'A01', '2021-04-11'),
       ('eagle',    'ad', 'B_eag_11', 'A03', '2021-01-01')
;


CREATE TABLE trees (
    TREE varchar(255),
    DESCR varchar(255),
    TREE_ID varchar(255),
    BIRD_ID varchar(255)
);

INSERT INTO trees (TREE, DESCR, TREE_ID, BIRD_ID)
VALUES ('oak tree', 'd', 'T_2021_1a', 'B_eag_11'),
       ('birch',    'v', 'T_2021_2a', 'B_mer_01'),
       ('oak tree', 'v', 'T_2021_3a', 'B_owl_01'),
       ('larch',    'v', 'T_2021_4a', 'B_pen_23'),
       ('larch',    'v', 'T_2021_5d', 'B_pen_23'),
       ('birch',    'd', 'T_2021_5a', 'B_eag_11')
;

我想要的是计算所有按面积和种类分组的鸟类种类。到目前为止这很简单。 但在下一步中,我想从 t2 获取树 ID。我这样做了:

select 
  B_spec,
  AMOUNT,
  TREE,
  B_age,
  B_age_juv,
  B_age_ad,
  B_track, 
  B_area, 
  date1
  from(
    select
      SPECIES as B_spec, 
      count(SPECIES) as AMOUNT,
      AGE as B_age,
      count(case when AGE = 'juv' then 1 end) as B_age_juv,
      count(case when AGE = 'ad' then 1 end) as B_age_ad,
      BIRD_TRACKING_ID as B_track, 
      AREA as B_area, 
      DATE_1 as date1,
      group_concat(TREE_ID) as TREE
    from birds
    left join trees t2
    on BIRD_TRACKING_ID = t2.BIRD_ID
    group by B_area, B_spec
    order by B_spec asc
    ) t1

得到了: 很明显是乱七八糟的,数错了。

我想要的是字段 TREE 中那只鸟访问过的所有树的树 ID。 此外,最好在一行中计算特定鸟类的数量,在另一行中计算访问过一棵树的鸟。

例如在 A03 区域我有 3 只老鹰。 2 个没有跟踪 ID,一个有跟踪 ID。所以 A03 上 3 只老鹰的输出应该是:

B_spec  |TREE                |AMOUNT| B_age_juv   |B_age_ad  |B_area |date1
---------------------------------------------------------------------------
eagle   |null                |2     | 1           |1         |A03    |2021-06-02
eagle   |T_2021_1a,T_2021_5a |1     | 0           |1         |A03    |2021-01-01

该日期应为在该特定区域首次观察到该物种鸟类的日期。在 2021-06-02 和 2021-06-15 上看到没有跟踪 ID 的 A3 上的老鹰。所以第一行有 2021-06-02 作为 date1.

数据不真实,企鹅不会飞。而我只能在QGIS中使用SQLite。

SQL Fiddle

您应该为没有 BIRD_TRACKING_ID 的鸟类再创建一个分组级别并使用条件聚合:

SELECT b.SPECIES B_spec, 
       GROUP_CONCAT(t.TREE_ID) TREE,
       COUNT(DISTINCT b.rowid) AMOUNT,
       COUNT(DISTINCT CASE WHEN AGE = 'juv' THEN b.rowid END) B_age_juv,
       COUNT(DISTINCT CASE WHEN AGE = 'ad' THEN b.rowid END) B_age_ad,
       b.AREA B_area,
       MIN(b.DATE_1) date1
FROM birds b LEFT JOIN trees t
ON b.BIRD_TRACKING_ID = t.BIRD_ID
GROUP BY B_area, B_spec, b.BIRD_TRACKING_ID IS NOT NULL
ORDER BY B_spec;

参见demo