创建一个 PostgreSQL 函数,该函数成为 table 从其他 table 检索相关数据的公式字段
Create a PostgreSQL function that becomes a formula field of a table retrieving related data from other table
上面的例子可以在 SQL 服务器上完成。它是一个函数,在另一个 table 上执行计算,同时获取当前 table 字段 Id 以列出来自其他 table、return 单个值的数据。
问题:如何使用 Postgre 做正确的事情SQL
SELECT TOP(5) * FROM Artists;
+------------+------------------+--------------+-------------+
| ArtistId | ArtistName | ActiveFrom | CountryId |
|------------+------------------+--------------+-------------|
| 1 | Iron Maiden | 1975-12-25 | 3 |
| 2 | AC/DC | 1973-01-11 | 2 |
| 3 | Allan Holdsworth | 1969-01-01 | 3 |
| 4 | Buddy Rich | 1919-01-01 | 6 |
| 5 | Devin Townsend | 1993-01-01 | 8 |
+------------+------------------+--------------+-------------+
SELECT TOP(5) * FROM Albums;
+-----------+------------------------+---------------+------------+-----------+
| AlbumId | AlbumName | ReleaseDate | ArtistId | GenreId |
|-----------+------------------------+---------------+------------+-----------|
| 1 | Powerslave | 1984-09-03 | 1 | 1 |
| 2 | Powerage | 1978-05-05 | 2 | 1 |
| 3 | Singing Down the Lane | 1956-01-01 | 6 | 3 |
| 4 | Ziltoid the Omniscient | 2007-05-21 | 5 | 1 |
| 5 | Casualties of Cool | 2014-05-14 | 5 | 1 |
+-----------+------------------------+---------------+------------+-----------+
函数
CREATE FUNCTION [dbo].[ufn_AlbumCount] (@ArtistId int)
RETURNS smallint
AS
BEGIN
DECLARE @AlbumCount int;
SELECT @AlbumCount = COUNT(AlbumId)
FROM Albums
WHERE ArtistId = @ArtistId;
RETURN @AlbumCount;
END;
GO
现在,(在 SQL 服务器上)用 ALTER TABLE Artists ADD AlbumCount AS dbo.ufn_AlbumCount(ArtistId);
更新前 table 字段后,可以列出并得到以下结果。
+------------+------------------+--------------+-------------+--------------+
| ArtistId | ArtistName | ActiveFrom | CountryId | AlbumCount |
|------------+------------------+--------------+-------------+--------------|
| 1 | Iron Maiden | 1975-12-25 | 3 | 5 |
| 2 | AC/DC | 1973-01-11 | 2 | 3 |
| 3 | Allan Holdsworth | 1969-01-01 | 3 | 2 |
| 4 | Buddy Rich | 1919-01-01 | 6 | 1 |
| 5 | Devin Townsend | 1993-01-01 | 8 | 3 |
| 6 | Jim Reeves | 1948-01-01 | 6 | 1 |
| 7 | Tom Jones | 1963-01-01 | 4 | 3 |
| 8 | Maroon 5 | 1994-01-01 | 6 | 0 |
| 9 | The Script | 2001-01-01 | 5 | 1 |
| 10 | Lit | 1988-06-26 | 6 | 0 |
+------------+------------------+--------------+-------------+--------------+
但是如何在 postgresql 上实现这个?
Postgres 不支持“虚拟”计算列(即在运行时生成的计算列),因此没有完全等效的列。最有效的解决方案是计算这个的视图:
create view artists_with_counts
as
select a.*,
coalesce(t.album_count, 0) as album_count
from artists a
left join (
select artist_id, count(*) as album_count
from albums
group by artist_id
) t on a.artist_id = t.artist_id;
另一种选择是创建一个可用作 select 中的“虚拟列”的函数 - 但由于这是逐行完成的,因此这将比视图慢得多。
create function album_count(p_artist artists)
returns bigint
as
$$
select count(*)
from albums a
where a.artist_id = p_artist.artist_id;
$$
language sql
stable;
那么您可以将其作为一列包括在内:
select a.*, a.album_count
from artists a;
使用这样的函数,需要在函数引用前加上 table 别名(或者,您可以使用 album_count(a)
)
上面的例子可以在 SQL 服务器上完成。它是一个函数,在另一个 table 上执行计算,同时获取当前 table 字段 Id 以列出来自其他 table、return 单个值的数据。
问题:如何使用 Postgre 做正确的事情SQL
SELECT TOP(5) * FROM Artists;
+------------+------------------+--------------+-------------+
| ArtistId | ArtistName | ActiveFrom | CountryId |
|------------+------------------+--------------+-------------|
| 1 | Iron Maiden | 1975-12-25 | 3 |
| 2 | AC/DC | 1973-01-11 | 2 |
| 3 | Allan Holdsworth | 1969-01-01 | 3 |
| 4 | Buddy Rich | 1919-01-01 | 6 |
| 5 | Devin Townsend | 1993-01-01 | 8 |
+------------+------------------+--------------+-------------+
SELECT TOP(5) * FROM Albums;
+-----------+------------------------+---------------+------------+-----------+
| AlbumId | AlbumName | ReleaseDate | ArtistId | GenreId |
|-----------+------------------------+---------------+------------+-----------|
| 1 | Powerslave | 1984-09-03 | 1 | 1 |
| 2 | Powerage | 1978-05-05 | 2 | 1 |
| 3 | Singing Down the Lane | 1956-01-01 | 6 | 3 |
| 4 | Ziltoid the Omniscient | 2007-05-21 | 5 | 1 |
| 5 | Casualties of Cool | 2014-05-14 | 5 | 1 |
+-----------+------------------------+---------------+------------+-----------+
函数
CREATE FUNCTION [dbo].[ufn_AlbumCount] (@ArtistId int)
RETURNS smallint
AS
BEGIN
DECLARE @AlbumCount int;
SELECT @AlbumCount = COUNT(AlbumId)
FROM Albums
WHERE ArtistId = @ArtistId;
RETURN @AlbumCount;
END;
GO
现在,(在 SQL 服务器上)用 ALTER TABLE Artists ADD AlbumCount AS dbo.ufn_AlbumCount(ArtistId);
更新前 table 字段后,可以列出并得到以下结果。
+------------+------------------+--------------+-------------+--------------+
| ArtistId | ArtistName | ActiveFrom | CountryId | AlbumCount |
|------------+------------------+--------------+-------------+--------------|
| 1 | Iron Maiden | 1975-12-25 | 3 | 5 |
| 2 | AC/DC | 1973-01-11 | 2 | 3 |
| 3 | Allan Holdsworth | 1969-01-01 | 3 | 2 |
| 4 | Buddy Rich | 1919-01-01 | 6 | 1 |
| 5 | Devin Townsend | 1993-01-01 | 8 | 3 |
| 6 | Jim Reeves | 1948-01-01 | 6 | 1 |
| 7 | Tom Jones | 1963-01-01 | 4 | 3 |
| 8 | Maroon 5 | 1994-01-01 | 6 | 0 |
| 9 | The Script | 2001-01-01 | 5 | 1 |
| 10 | Lit | 1988-06-26 | 6 | 0 |
+------------+------------------+--------------+-------------+--------------+
但是如何在 postgresql 上实现这个?
Postgres 不支持“虚拟”计算列(即在运行时生成的计算列),因此没有完全等效的列。最有效的解决方案是计算这个的视图:
create view artists_with_counts
as
select a.*,
coalesce(t.album_count, 0) as album_count
from artists a
left join (
select artist_id, count(*) as album_count
from albums
group by artist_id
) t on a.artist_id = t.artist_id;
另一种选择是创建一个可用作 select 中的“虚拟列”的函数 - 但由于这是逐行完成的,因此这将比视图慢得多。
create function album_count(p_artist artists)
returns bigint
as
$$
select count(*)
from albums a
where a.artist_id = p_artist.artist_id;
$$
language sql
stable;
那么您可以将其作为一列包括在内:
select a.*, a.album_count
from artists a;
使用这样的函数,需要在函数引用前加上 table 别名(或者,您可以使用 album_count(a)
)