2

Suppose, there are two tables in db:

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

In real world registries is just a csv-file and rows is lines of the files. In my scala-slick application, I want to know how many lines in each file.

registries:

1,foo,...
2,bar,...
3,baz,...

rows:

aaa,1,...
bbb,1,...
ccc,2,...

desired result:

1,foo,... - 2
2,bar,... - 1
3,baz,... - 0

My code now is (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 is bad idea, I know it)

How can I do getRegistryWithLength using single sql query?

I could add column row_n into table registries, but then I'll be forced to do updating column row_n after delete/insert query of rows table.

How can I do automatic calculation column row_n in table registries on db server side?

sheh
  • 1,003
  • 1
  • 9
  • 31
  • It's unclear to me what you want exactly. `number of rows`? Or a row-number for each row? Please clarify. Add sample data and the expected result to clarify. You want an SQL solution, so it's unwise to write a question that only people familiar with scala and slick can understand. – Erwin Brandstetter Sep 10 '15 at 15:45
  • Apologize, I updated question. It's about count number of `rows`. I hope on scala solution, but if I'll get SQL solution it will be good too. – sheh Sep 10 '15 at 16:06

2 Answers2

1

The basic query could be:

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);

The LEFT [OUTER] JOIN is essential so you do not filter rows from registry without related rows in rows.

COALESCE to return 0 instead of NULL where no related rows are found.

There are many related answers on SO. One here:

You could wrap this in a VIEW for convenience:

CREATE VIEW reg_rn AS
SELECT ...

... which you query like a table.

Aside: It's unwise to use reserved SQL key words as identifiers. row is a no-go for a column name (even if allowed in Postgres).

Community
  • 1
  • 1
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
0

Thanks Erwin Brandstetter for awesome answer, using it, I wrote code for my scala-slick application.

Scala code looks much more complicated than plain 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))
}

but it works!

Community
  • 1
  • 1
sheh
  • 1,003
  • 1
  • 9
  • 31