在服务器端使用 table 计算 table 列
Calculate table column using over table on server side
假设,db:
中有两个table
Table registries
:
Column | Type |
--------------------+-----------------------------+---------
registry_id | integer | not null
name | character varying | not null
...
uploaded_at | timestamp without time zone | not null
Table rows
:
Column | Type | Modifiers
---------------+-----------------------------+-----------
row_id | character varying | not null
registry_id | integer | not null
row | character varying | not null
在现实世界中,registries
只是一个 csv 文件,rows
是文件的行。在我的 scala-slick 应用程序中,我想知道每个文件中有多少行。
registries
:
1,foo,...
2,bar,...
3,baz,...
rows
:
aaa,1,...
bbb,1,...
ccc,2,...
想要的结果:
1,foo,... - 2
2,bar,... - 1
3,baz,... - 0
我现在的代码是 (slick-3.0):
def getRegistryWithLength(rId: Int) = {
val q1 = registries.filter(_.registryId===rId).take(1).result.headOption
val q2 = rows.filter(_.registryId===rId).length.result
val registry = Await.result(db.run(q1), 5.seconds)
val length = Await.result(db.run(q2), 5.seconds)
(registry, length)
}
(Await
是个坏主意,我知道)
我怎样才能 getRegistryWithLength
使用单个 sql
查询?
我可以将列 row_n
添加到 table registries
中,但是我将被迫在 delete/insert 查询之后更新列 row_n
rows
table.
如何在数据库服务器端自动计算 table registries
中的 row_n
列?
基本查询可以是:
SELECT r.*, COALESCE(n.ct, 0) AS ct
FROM registry r
LEFT JOIN (
SELECT registry_id, count(*) AS ct
FROM rows
GROUP BY registry_id
) n USING (registry_id);
LEFT [OUTER]
JOIN
是必不可少的,因此您不会从 rows
.[=22= 中没有相关行的注册表中过滤行]
COALESCE
到 return 0 而不是找不到相关行的 NULL。
SO上有很多相关的回答。这里有一个:
为方便起见,您可以将其包装在 VIEW
中:
CREATE VIEW reg_rn AS
SELECT ...
... 您可以像 table.
一样查询
旁白:使用 reserved SQL key words 作为标识符是不明智的。 row
是列名的禁忌(即使在 Postgres 中允许)。
感谢 Erwin Brandstetter 的精彩回答,使用它,我为我的 scala-slick 应用程序编写了代码。
Scala 代码看起来比普通代码复杂得多 sql:
val registryQuery = registries.filter(_.userId === userId)
val rowQuery = rows groupBy(_.registryId) map { case (regId, rowItems) => (regId, rowItems.length)}
val q = registryQuery joinLeft rowQuery on (_.registryId === _._1) map {
case (registry, rowsCnt) => (registry, rowsCnt.map(_._2))
}
但它有效!
假设,db:
中有两个tableTable registries
:
Column | Type |
--------------------+-----------------------------+---------
registry_id | integer | not null
name | character varying | not null
...
uploaded_at | timestamp without time zone | not null
Table rows
:
Column | Type | Modifiers
---------------+-----------------------------+-----------
row_id | character varying | not null
registry_id | integer | not null
row | character varying | not null
在现实世界中,registries
只是一个 csv 文件,rows
是文件的行。在我的 scala-slick 应用程序中,我想知道每个文件中有多少行。
registries
:
1,foo,...
2,bar,...
3,baz,...
rows
:
aaa,1,...
bbb,1,...
ccc,2,...
想要的结果:
1,foo,... - 2
2,bar,... - 1
3,baz,... - 0
我现在的代码是 (slick-3.0):
def getRegistryWithLength(rId: Int) = {
val q1 = registries.filter(_.registryId===rId).take(1).result.headOption
val q2 = rows.filter(_.registryId===rId).length.result
val registry = Await.result(db.run(q1), 5.seconds)
val length = Await.result(db.run(q2), 5.seconds)
(registry, length)
}
(Await
是个坏主意,我知道)
我怎样才能 getRegistryWithLength
使用单个 sql
查询?
我可以将列 row_n
添加到 table registries
中,但是我将被迫在 delete/insert 查询之后更新列 row_n
rows
table.
如何在数据库服务器端自动计算 table registries
中的 row_n
列?
基本查询可以是:
SELECT r.*, COALESCE(n.ct, 0) AS ct
FROM registry r
LEFT JOIN (
SELECT registry_id, count(*) AS ct
FROM rows
GROUP BY registry_id
) n USING (registry_id);
LEFT [OUTER]
JOIN
是必不可少的,因此您不会从 rows
.[=22= 中没有相关行的注册表中过滤行]
COALESCE
到 return 0 而不是找不到相关行的 NULL。
SO上有很多相关的回答。这里有一个:
为方便起见,您可以将其包装在 VIEW
中:
CREATE VIEW reg_rn AS
SELECT ...
... 您可以像 table.
一样查询旁白:使用 reserved SQL key words 作为标识符是不明智的。 row
是列名的禁忌(即使在 Postgres 中允许)。
感谢 Erwin Brandstetter 的精彩回答,使用它,我为我的 scala-slick 应用程序编写了代码。
Scala 代码看起来比普通代码复杂得多 sql:
val registryQuery = registries.filter(_.userId === userId)
val rowQuery = rows groupBy(_.registryId) map { case (regId, rowItems) => (regId, rowItems.length)}
val q = registryQuery joinLeft rowQuery on (_.registryId === _._1) map {
case (registry, rowsCnt) => (registry, rowsCnt.map(_._2))
}
但它有效!