有人告诉我,PostgreSQL是比MySQL更好的选择,用于显示分层数据,所以我安装了PostgreSQL,我已经准备好了。
这是我标题中的架构(从pgAdmin复制):
CREATE TABLE public.gz_life_mammals (
id integer NOT NULL,
taxon text NOT NULL,
parent text NOT NULL,
parent_id smallint NOT NULL,
slug text,
name_common text,
plural text,
extinct smallint NOT NULL,
rank smallint NOT NULL,
key smallint NOT NULL,
CONSTRAINT "Primary Key" PRIMARY KEY (id)
);
这是我的数据库连接和第一个查询:
$dbh = pg_connect("host=localhost dbname=geozoo user=postgres");
if (!$dbh) {
die("Error in connection: " . pg_last_error());
}
$sql = "SELECT * FROM gz_life_mammals";
$result = pg_query($dbh, $sql);
while ($row = pg_fetch_array($result)) {
echo "ID: " . $row[0] . " | ";
echo "Taxon: " . $row[1] . " | ";
echo "ParentID: " . $row[3] . "<br>";
}
// free memory
pg_free_result($result);
// close connection
pg_close($dbh);
此练习最重要的表格字段是前四个(id
,taxon
,parent
和parent_id
。数据如下所示:
ID | TAXON | PARENT | PARENT_ID
1 | Mammalia | Chordata | 1
2 | Carnivora | Mammalia | 2
3 | Canidae | Carnivora | 3
4 | Canis | Canidae | 4
5 | Canis-lupus | Canis | 5
6 | Canis-latrans | Canis | 5
最后两行代表狼(Canis lupus)和土狼(Canis latrans)。最后,我希望能够显示孩子,孙子女,父母,曾祖父母等的名字。但是现在我只是想显示后代的数量。例如,如果我导航到MySite / life / mammalia,我可能会看到以下显示:
Orders: 19
Families: 58
Genera: 688
Species: 8,034
如果我导航到MySite / life / canidae,可能会显示如下内容:
Genera: 6
Species: 37
有人能告诉我编写这种查询并显示结果的最佳方法(使用PHP)吗?
答案 0 :(得分:1)
鉴于表格:
select * from gz_life_mammals;
id | taxon | parent | parent_id
----+---------------+-----------+-----------
1 | Mammalia | Chordata | 1
2 | Carnivora | Mammalia | 2
3 | Canidae | Carnivora | 3
4 | Canis | Canidae | 4
5 | Canis-lupus | Canis | 5
6 | Canis-latrans | Canis | 5
(6 rows)
以及将parent_id转换为分类等级名称的函数:
create function tax_rank(id integer) returns text as $$
select case id
when 1 then 'Classes'
when 2 then 'Orders'
when 3 then 'Families'
when 4 then 'Genera'
when 5 then 'Species'
end;
$$ language sql;
您可以使用以下递归查询查询后代的数量:
with recursive hier(taxon,parent_id) as (
select m.taxon, null::integer
from gz_life_mammals m
where taxon='Mammalia' --<< substitute me
union all
select m.taxon, m.parent_id
from hier, gz_life_mammals m
where m.parent=hier.taxon
)
select tax_rank(parent_id),
count(*) num_of_desc
from hier
where parent_id is not null
group by parent_id
order by parent_id;
tax_rank | num_of_desc
----------+-------------
Orders | 1
Families | 1
Genera | 1
Species | 2
(4 rows)
有趣的部分在with recursive
内。查询的第一部分选择层次结构的根行。第二部分(在union all
之后)被递归调用,并且每次都将直接后代添加到前一个结果集。阅读this以了解其工作原理。
构建层次结构后,可以根据需要进行表示。在上面的例子中,只显示了许多后代。你也可以得到名字:
with recursive hier(taxon,parent_id) as (
...
)
select tax_rank(parent_id),
taxon as name
from hier
where parent_id is not null
order by parent_id;
tax_rank | name
----------+---------------
Orders | Carnivora
Families | Canidae
Genera | Canis
Species | Canis-lupus
Species | Canis-latrans
(5 rows)
同一行:
with recursive hier(taxon,parent_id) as (
...
)
select tax_rank(parent_id),
string_agg(taxon,', ') as names
from hier
where parent_id is not null
group by parent_id
order by parent_id;
tax_rank | names
----------+----------------------------
Orders | Carnivora
Families | Canidae
Genera | Canis
Species | Canis-lupus, Canis-latrans
(4 rows)
等等......