连接不同维度的表的最有效方法是什么?

时间:2018-07-19 23:42:38

标签: sql postgresql kotlin plpgsql

我有以下架构:

CREATE TABLE products (
  id                    BIGSERIAL NOT NULL,
  created_at_timestamp  TIMESTAMP NOT NULL DEFAULT NOW(),
  last_update_timestamp TIMESTAMP NOT NULL DEFAULT NOW(),
  PRIMARY KEY (id)
);

CREATE TABLE product_names (
  product_id BIGINT NOT NULL,
  language   TEXT   NOT NULL,
  name       TEXT   NOT NULL,
  PRIMARY KEY (product_id, language),
  FOREIGN KEY (product_id) REFERENCES products (id)
);

CREATE TABLE product_summaries (
  product_id BIGINT NOT NULL,
  language   TEXT   NOT NULL,
  summary    TEXT   NOT NULL,
  PRIMARY KEY (product_id, language),
  FOREIGN KEY (product_id) REFERENCES products (id)
);

我想select所有产品。

但是,您会看到产品包含名称和摘要(每种语言)的列表。

我可以检索所有产品

SELECT * FROM products

然后迭代所有行(在本例中为Kotlin),然后请求名称和摘要:

SELECT * FROM product_names WHERE product_id = $id

SELECT * FROM product_summaries WHERE product_id = $id

但是,这似乎效率低下,因为我要对数据库进行3个单独的查询。

我虽然使用JOIN来通过一个查询来获取所有这些信息,但是随后我为每个product_namesproduct_summaries条目获得了多个重复的行。

最后,有没有更好的方法可以在一个查询中请求所有这些数据?

2 个答案:

答案 0 :(得分:1)

您绝对不想执行多个查询,然后在代码中对其进行迭代。效率低下。当您执行第二个07-19 14:29:52.971 9123-9390/com.packaename.abc E/Unity: AndroidJavaException: java.lang.ClassNotFoundException: io.fabric.unity.android.FabricInitializer java.lang.ClassNotFoundException: io.fabric.unity.android.FabricInitializer at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.unity3d.player.UnityPlayer.nativeRender(Native Method) at com.unity3d.player.UnityPlayer.c(Unknown Source) at com.unity3d.player.UnityPlayer$c$1.handleMessage(Unknown Source) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:207) at com.unity3d.player.UnityPlayer$c.run(Unknown Source) Caused by: java.lang.ClassNotFoundException: Didn't find class "io.fabric.unity.android.FabricInitializer" on path: DexPathList[[zip file "/data/app/com.packaename.abc-1/base.apk"],nativeLibraryDirectories=[/data/app/com.packaename.abc-1/lib/arm, /data/app/com.packaename.abc-1/base.apk!/lib/armeabi-v7a, /vendor/lib, /system/lib]] at dalvik.system.BaseDexClassLo 时,您需要在JOIN中包含language。那应该使您避免重复行。对于[products.id,product_names.language]

的每个唯一组合,应该为您提供一行
JOIN

答案 1 :(得分:0)

我找到了一种方法:

SELECT * FROM products as p INNER JOIN
(SELECT json_agg(product_names) as names, product_id FROM product_names GROUP BY product_id) as tb_names ON tb_names.product_id = p.id
INNER JOIN
(SELECT json_agg(product_summaries) as summaries, product_id FROM product_summaries GROUP BY product_id) as tb_summaries ON tb_summaries.product_id = p.id

返回:

1 | 2018-07-20 09:36:21.56904 | 2018-07-20 09:36:21.56904 | [{"product_id":1,"language":"EN","name":"lol"}, {"product_id":1,"language":"DE","name":"lel"}] | 1 [{"product_id":1,"language":"EN","summary":"deded"}, {"product_id":1,"language":"DE","summary":"rererere"}, {"product_id":1,"language":"FR","summary":"jejejeje"}] | 1

基本上我正在将多维表转换为JSON:)

Postgres很棒!