Postgres 中的组合 SQL 计数查询
Combinational SQL count query in Postgres
我有一些电台存储在一个简单的 stations
collection:
+----+-----------+
| id | name |
+----+-----------+
| 1 | Station A |
+----+-----------+
| 2 | Station B |
+----+-----------+
| 3 | Station C |
+----+-----------+
| 4 | Station D |
+----+-----------+
我在 rides
collection:
中存储了一些游乐设施
+----+---------------+-------------+
| id | fromStationId | toStationId |
+----+---------------+-------------+
| 1 | 3 | 4 |
+----+---------------+-------------+
| 2 | 2 | 1 |
+----+---------------+-------------+
| 3 | 1 | 1 |
+----+---------------+-------------+
| 4 | 3 | 2 |
+----+---------------+-------------+
我想在所有可能的 fromStation
姓名和 toStation
姓名对之间创建所有 inter-station 游乐设施的计数列表,结果如下所示:
[
{
"fromStation": "Station A",
"toStation": "Station A",
"count": 1196
},
{
"fromStation": "Station A",
"toStation": "Station B",
"count": 1
},
{
"fromStation": "Station A",
"toStation": "Station C",
"count": 173
},
]
And so on for all other combinations...
如何获得所有可能的 two-pair 车站名称组合,然后计算其中的乘车次数?我正在使用最新版本的 Postgres。
SELECT
c.from_station,
c.to_station,
COUNT(*)
FROM stations s1
JOIN stations s2 ON s1.station <> s2.station -- 1
JOIN connections c ON s1.station = c.from_station AND s2.station = c.to_station -- 2
GROUP BY c.from_station, c.to_station -- 3
- 在站上创建一个自加入table。
<>
加入条件确保不会加入同一站。所有其他站点将相互连接,从而创建所有组合
- 在您的连接table上加入这个结果,使用来自连接
from
和to
点的自连接的两个站点列
- 现在您可以按
from
和 to
和 COUNT(*)
聚合这个。
如果你想识别from
站等于to
站的情况,你可以改变
JOIN stations s2 ON s1.station <> s2.station
简单化为:
CROSS JOIN stations s2
如果你想获得问题中显示的 JSON 对象:
SELECT
json_agg(connection) -- 2
FROM (
SELECT
json_build_object( -- 1
'fromStation', c.from_station,
'toStation', c.to_station,
'count', COUNT(*)
) as connection
FROM stations s1
JOIN stations s2 ON s1.station <> s2.station
JOIN connections c ON s1.station = c.from_station AND s2.station = c.to_station
GROUP BY c.from_station, c.to_station
) s
- 根据您在上面创建的列创建 JSON 对象
- 将它们聚合成一个 JSON 数组。
先聚合游乐设施,然后将 ID 解析为名称:
SELECT f.name AS from_station, t.name AS to_station, count
FROM (
SELECT from_station_id, to_station_id, count(*) AS count
FROM rides
GROUP BY 1, 2
) r
JOIN stations f ON f.id = r.from_station_id
JOIN stations t ON t.id = r.to_station_id
ORDER BY 1, 2; -- optional order
当然,这只会产生与实际游乐设施的组合。如果您需要包含没有任何游乐设施的组合,则需要 OUTER
连接到 stations
table 本身的笛卡尔积。类似于:
-- include all combinations (even without rides)
SELECT from_station, to_station, COALESCE(count, 0) AS count
FROM (
SELECT from_station_id, to_station_id, count(*) AS count
FROM rides
GROUP BY 1, 2
) r
RIGHT JOIN (
SELECT f.id AS from_id, f.name AS from_station
, t.id AS to_id , t.name AS to_station
FROM stations f CROSS JOIN stations t
) s ON s.from_id = r.from_station_id
AND s.to_id = r.to_station_id
ORDER BY 1, 2; -- optional order
同样,在 加入车站之前汇总游乐设施更便宜。
要将其包装为 JSON 数组或记录,只需:
SELECT json_agg(sub)
FROM (
-- query from above
) sub;
db<>fiddle here
我有一些电台存储在一个简单的 stations
collection:
+----+-----------+
| id | name |
+----+-----------+
| 1 | Station A |
+----+-----------+
| 2 | Station B |
+----+-----------+
| 3 | Station C |
+----+-----------+
| 4 | Station D |
+----+-----------+
我在 rides
collection:
+----+---------------+-------------+
| id | fromStationId | toStationId |
+----+---------------+-------------+
| 1 | 3 | 4 |
+----+---------------+-------------+
| 2 | 2 | 1 |
+----+---------------+-------------+
| 3 | 1 | 1 |
+----+---------------+-------------+
| 4 | 3 | 2 |
+----+---------------+-------------+
我想在所有可能的 fromStation
姓名和 toStation
姓名对之间创建所有 inter-station 游乐设施的计数列表,结果如下所示:
[
{
"fromStation": "Station A",
"toStation": "Station A",
"count": 1196
},
{
"fromStation": "Station A",
"toStation": "Station B",
"count": 1
},
{
"fromStation": "Station A",
"toStation": "Station C",
"count": 173
},
]
And so on for all other combinations...
如何获得所有可能的 two-pair 车站名称组合,然后计算其中的乘车次数?我正在使用最新版本的 Postgres。
SELECT
c.from_station,
c.to_station,
COUNT(*)
FROM stations s1
JOIN stations s2 ON s1.station <> s2.station -- 1
JOIN connections c ON s1.station = c.from_station AND s2.station = c.to_station -- 2
GROUP BY c.from_station, c.to_station -- 3
- 在站上创建一个自加入table。
<>
加入条件确保不会加入同一站。所有其他站点将相互连接,从而创建所有组合 - 在您的连接table上加入这个结果,使用来自连接
from
和to
点的自连接的两个站点列 - 现在您可以按
from
和to
和COUNT(*)
聚合这个。
如果你想识别from
站等于to
站的情况,你可以改变
JOIN stations s2 ON s1.station <> s2.station
简单化为:
CROSS JOIN stations s2
如果你想获得问题中显示的 JSON 对象:
SELECT
json_agg(connection) -- 2
FROM (
SELECT
json_build_object( -- 1
'fromStation', c.from_station,
'toStation', c.to_station,
'count', COUNT(*)
) as connection
FROM stations s1
JOIN stations s2 ON s1.station <> s2.station
JOIN connections c ON s1.station = c.from_station AND s2.station = c.to_station
GROUP BY c.from_station, c.to_station
) s
- 根据您在上面创建的列创建 JSON 对象
- 将它们聚合成一个 JSON 数组。
先聚合游乐设施,然后将 ID 解析为名称:
SELECT f.name AS from_station, t.name AS to_station, count
FROM (
SELECT from_station_id, to_station_id, count(*) AS count
FROM rides
GROUP BY 1, 2
) r
JOIN stations f ON f.id = r.from_station_id
JOIN stations t ON t.id = r.to_station_id
ORDER BY 1, 2; -- optional order
当然,这只会产生与实际游乐设施的组合。如果您需要包含没有任何游乐设施的组合,则需要 OUTER
连接到 stations
table 本身的笛卡尔积。类似于:
-- include all combinations (even without rides)
SELECT from_station, to_station, COALESCE(count, 0) AS count
FROM (
SELECT from_station_id, to_station_id, count(*) AS count
FROM rides
GROUP BY 1, 2
) r
RIGHT JOIN (
SELECT f.id AS from_id, f.name AS from_station
, t.id AS to_id , t.name AS to_station
FROM stations f CROSS JOIN stations t
) s ON s.from_id = r.from_station_id
AND s.to_id = r.to_station_id
ORDER BY 1, 2; -- optional order
同样,在 加入车站之前汇总游乐设施更便宜。
要将其包装为 JSON 数组或记录,只需:
SELECT json_agg(sub)
FROM (
-- query from above
) sub;
db<>fiddle here