Sql 查询结果作为列值

Sql 查询结果作为列值,sql,postgresql,Sql,Postgresql,我有三张桌子: 经验教训: CREATE TABLE lessons ( id SERIAL PRIMARY KEY, title text NOT NULL, description text NOT NULL, vocab_count integer NOT NULL ); +----+------------+------------------+-------------+ | id | title | description | v

我有三张桌子:

经验教训:

CREATE TABLE lessons (
    id SERIAL PRIMARY KEY,
    title text NOT NULL,
    description text NOT NULL,
    vocab_count integer NOT NULL
);

+----+------------+------------------+-------------+
| id |   title    |   description    | vocab_count |
+----+------------+------------------+-------------+
|  1 | lesson_one | this is a lesson |           3 |
|  2 | lesson_two | another lesson   |           2 |
+----+------------+------------------+-------------+
第十一课词汇:

CREATE TABLE lesson_vocabulary (
    lesson_id integer REFERENCES lessons(id),
    vocabulary_id integer REFERENCES vocabulary(id)
);

+-----------+---------------+
| lesson_id | vocabulary_id |
+-----------+---------------+
|         1 |             1 |
|         1 |             2 |
|         1 |             3 |
|         2 |             2 |
|         2 |             4 |
+-----------+---------------+
CREATE TABLE vocabulary (
    id integer PRIMARY KEY,
    hiragana text NOT NULL,
    reading text NOT NULL,
    meaning text[] NOT NULL
);
词汇:

CREATE TABLE lesson_vocabulary (
    lesson_id integer REFERENCES lessons(id),
    vocabulary_id integer REFERENCES vocabulary(id)
);

+-----------+---------------+
| lesson_id | vocabulary_id |
+-----------+---------------+
|         1 |             1 |
|         1 |             2 |
|         1 |             3 |
|         2 |             2 |
|         2 |             4 |
+-----------+---------------+
CREATE TABLE vocabulary (
    id integer PRIMARY KEY,
    hiragana text NOT NULL,
    reading text NOT NULL,
    meaning text[] NOT NULL
);
每节课包含多个词汇,每个词汇可以包含在多节课中

当我向lesson_词汇表添加更多行时,如何计算和更新lessons表的vocab_count列。这可能吗?我该怎么做


谢谢

您可以使用SQL触发器来达到您的目的。这将类似于

触发器看起来有点像这样。我正在使用oraclesql,但对于任何其他实现都会有一些小的调整

CREATE TRIGGER vocab_trigger
AFTER INSERT ON lesson_vocabulary
FOR EACH ROW 
begin
   for lesson_cur in (select LESSON_ID, COUNT(VOCABULARY_ID) voc_cnt from LESSON_VOCABULARY group by LESSON_ID) LOOP
   update LESSONS
       set VOCAB_COUNT = LESSON_CUR.VOC_CNT
       where id = LESSON_CUR.LESSON_ID;
  end loop; 
END;

最好创建一个计算该值的视图(并去掉lessons表中的列):


如果确实希望在每次更改lesson_词汇表时更新lessons表,则可以在触发器中运行如下update语句:

update lessons l
  set vocab_count = t.cnt
from (
  select lesson_id, count(*) as cnt
  from lesson_vocabulary
  group by lesson_id
) t
where t.lesson_id = l.id;

我建议使用查询来查询此信息:

select l.*,
       (select count(*)
        from lesson_vocabulary lv
        where lv.lesson_id = l.lesson_id
       ) as vocabulary_cnt
from lessons l;
lesson\u词汇表(lesson\u id)
上有一个索引,这应该非常快

我建议您在
更新时使用此选项,因为数据仍然正确

我建议不要使用触发器,因为它更简单


我建议使用聚合子查询,因为它应该更快,特别是当您在
lessons
表上进行筛选时。

您需要一个触发器。但一般来说,您不应该将信息存储在可以从现有数据派生的关系数据库中。为什么不创建一个返回该计数的视图呢?好的,我明白你的意思。所以我根本不应该为此创建一个列,而只是创建一个视图来显示每节课的所有链接词汇表?另外,如果我想在页面上显示包括每节课词汇表计数在内的课程信息。我会先获取lessons表中的所有行,然后对每一行运行一个查询来计算我自己的词汇量吗?有没有一种方法可以一步完成呢?根据我的经验,对派生表的连接并不是很慢,而且过滤条件很容易被Postgres推下。但是,如果对许多行执行此操作,则相关子查询的速度往往较慢。它必须处理的行越多(来自课程表),差异就越大gets@a_horse_with_no_name . . . 如果正在选择第一个表中的所有行,则不会。但是,如果行在外部查询中被过滤,那么我认为Postgres不会将过滤推送到聚合子查询,因此聚合要做更多的工作