- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当一个表不是数组值,而另一个表的数组值可以包含多个值时,我似乎找不到通过数组列连接两个表的技巧。当存在单值数组时它确实有效。
这是我正在谈论的一个简单的最小示例。真实的表在数组列 FWIW 上有 GIN 索引。这些不是,但查询的行为是相同的。
DROP TABLE IF EXISTS eg_person;
CREATE TABLE eg_person (id INT PRIMARY KEY, name TEXT);
INSERT INTO eg_person (id, name) VALUES
(1, 'alice')
, (2, 'bob')
, (3, 'charlie');
DROP TABLE IF EXISTS eg_assoc;
CREATE TABLE eg_assoc (aid INT PRIMARY KEY, actors INT[], benefactors INT[]);
INSERT INTO eg_assoc (aid, actors, benefactors) VALUES
(1, '{1}' , '{2}')
, (2, '{1,2}', '{3}')
, (3, '{1}' , '{2,3}')
, (4, '{4}' , '{1}');
SELECT aid, actors, a_person.name, benefactors, b_person.name
FROM eg_assoc
LEFT JOIN eg_person a_person on array[a_person.id] @> eg_assoc.actors
LEFT JOIN eg_person b_person on array[b_person.id] @> eg_assoc.benefactors;
实际结果是这样的。这里的问题是,如果 actors
或 benefactors
包含多个值,则 name 列会出现 NULL
。
aid | actors | name | benefactors | name
-----+--------+-------+-------------+---------
1 | {1} | alice | {2} | bob
2 | {1,2} | | {3} | charlie
3 | {1} | alice | {2,3} |
4 | {4} | | {1} | alice
我期待着这个:
aid | actors | name | benefactors | name
-----+--------+-------+-------------+---------
1 | {1} | alice | {2} | bob
2 | {1,2} | alice | {3} | charlie
2 | {1,2} | bob | {3} | charlie
3 | {1} | alice | {2,3} | bob
3 | {1} | alice | {2,3} | charlie
4 | {4} | | {1} | alice
如果我能让它看起来像这样,那就太好了:
aid | actors | name | benefactors | name
-----+--------+-------------+-------------+---------
1 | {1} | {alice} | {2} | {bob}
2 | {1,2} | {alice,bob} | {3} | {charlie}
3 | {1} | {alice} | {2,3} | {bob, charlie}
4 | {4} | | {1} | {alice}
我知道这个模式是非规范化的,如果需要的话我愿意使用正常的表示。然而,这是一个汇总查询,它已经涉及比我想要的更多的联接。
最佳答案
是的,overlap operator &&
can use a GIN index on arrays 。对于像这样的查询非常有用,可以在一组参与者中查找包含给定人员 (1
) 的行:
SELECT * FROM eg_assoc WHERE actors && '{1}'::int[]
但是,查询的逻辑是相反的,即查找 eg_assoc
数组中列出的所有人员。 GIN 索引在这里没有帮助。我们只需要 PK person.id
的 btree 索引。
基础知识:
以下查询完全按照给定的方式保留原始数组,包括可能的重复元素和元素的原始顺序。适用于一维数组。附加维度被折叠成单一维度。保留多个维度更复杂(但完全可能):
Postgres 9.4 或更高版本中的WITH ORDINALITY
SELECT aid, actors
, ARRAY(SELECT name
FROM unnest(e.actors) WITH ORDINALITY a(id, i)
JOIN eg_person p USING (id)
ORDER BY a.i) AS act_names
, benefactors
, ARRAY(SELECT name
FROM unnest(e.benefactors) WITH ORDINALITY b(id, i)
JOIN eg_person USING (id)
ORDER BY b.i) AS ben_names
FROM eg_assoc e;
横向
查询对于 PostgreSQL 9.3+。
SELECT e.aid, e.actors, a.act_names, e.benefactors, b.ben_names
FROM eg_assoc e
, LATERAL (
SELECT ARRAY( SELECT name
FROM generate_subscripts(e.actors, 1) i
JOIN eg_person p ON p.id = e.actors[i]
ORDER BY i)
) a(act_names)
, LATERAL (
SELECT ARRAY( SELECT name
FROM generate_subscripts(e.benefactors, 1) i
JOIN eg_person p ON p.id = e.benefactors[i]
ORDER BY i)
) b(ben_names);
db<> fiddle here 有几个变体。
<子>旧sqlfiddle
微妙的细节:如果找不到一个人,它就会被丢弃。如果在整个数组中找不到人员,这两个查询都会生成一个空数组 ('{}'
)。其他查询样式将返回 NULL
。我向 fiddle 添加了变体。
对于 Postgres 8.4+(其中引入了 generate_subsrcipts()
):
SELECT aid, actors
, ARRAY(SELECT name
FROM generate_subscripts(e.actors, 1) i
JOIN eg_person p ON p.id = e.actors[i]
ORDER BY i) AS act_names
, benefactors
, ARRAY(SELECT name
FROM generate_subscripts(e.benefactors, 1) i
JOIN eg_person p ON p.id = e.benefactors[i]
ORDER BY i) AS ben_names
FROM eg_assoc e;
即使在 Postgres 9.3 中,仍可能表现最佳。ARRAY
constructor比 array_agg() 更快。请参阅:
query provided by @a_horse 似乎可以完成这项工作,但它不可靠、具有误导性、可能不正确且不必要地昂贵。
由于两个不相关的连接而导致代理交叉连接。一种狡猾的反模式。请参阅:
在array_agg()
中使用DISTINCT
进行了表面修复,以消除生成的重复项,但这确实是在给 pig 涂上口红。它还消除了原始内容中的重复项,因为此时无法区分差异 - 这可能是不正确的。
表达式a_person.id = any(eg_assoc.actors)
有效,但消除了结果中的重复项(发生了两次次),除非指定,否则这是错误的。
原始数组元素的顺序不会保留。一般来说,这很棘手。但在这个查询中,情况变得更加严重,因为参与者和捐助者被倍增并再次变得不同,这保证了任意顺序。
外部 SELECT
中没有列别名会导致重复的列名称,这会导致某些客户端失败(没有别名时无法正常工作)。
min(actors)
和 min(benefactors)
毫无用处。通常,人们只需将列添加到 GROUP BY 中,而不是假聚合它们。但 eg_assoc.aid
无论如何都是 PK 列(覆盖 GROUP BY
中的整个表),因此甚至没有必要。只是 Actor 、捐助者
。
聚合整个结果一开始就是浪费时间和精力。使用不会将基行相乘的更智能查询,这样您就不必将它们聚合回来。
关于sql - 具有多个值的数组列上的 LEFT OUTER JOIN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28589773/
我正在 csv 上使用 hadoop 来分析一些数据。我使用sql/mysql(不确定)来分析数据,现在陷入了僵局。 我花了好几个小时在谷歌上搜索,却没有找到任何相关的东西。我需要一个查询,在该查询中
我正在为 Bootstrap 网格布局的“简单”任务而苦苦挣扎。我希望在大视口(viewport)上有 4 列,然后在中型设备上有 2 列,最后在较小的设备上只有 1 列。 当我测试我的代码片段时,似
对于这个令人困惑的标题,我深表歉意,我想不出这个问题的正确措辞。相反,我只会给你背景信息和目标: 这是在一个表中,一个人可能有也可能没有多行数据,这些行可能包含相同的 activity_id 值,也可
具有 3 列的数据库表 - A int , B int , C int 我的问题是: 如何使用 Sequelize 结果找到 A > B + C const countTasks = await Ta
我在通过以下功能编写此查询时遇到问题: 首先按第 2 列 DESC 排序,然后从“不同的第 1 列”中选择 只有 Column1 是 DISTINCT 此查询没有帮助,因为它首先从第 1 列中进行选择
使用 Bootstrap 非常有趣和有帮助,目前我在创建以下需求时遇到问题。 “使用 bootstrap 在桌面上有 4 列,在平板电脑上有 2 列,在移动设备上有 1 列”谁能告诉我正确的结构 最佳
我是 R 新手,正在问一个非常基本的问题。当然,我在尝试从所提供的示例中获取指导的同时做了功课here和 here ,但无法在我的案例中实现这个想法,即可能是由于我的问题中的比较维度更大。 我的实
通常我会使用 R 并执行 merge.by,但这个文件似乎太大了,部门中的任何一台计算机都无法处理它! (任何从事遗传学工作的人的附加信息)本质上,插补似乎删除了 snp ID 的 rs 数字,我只剩
我有一个 df , delta1 delta2 0 -1 2 0 -1 0 0 0 我想知道如何分配 delt
您好,我想知道是否可以执行以下操作。显然,我已经尝试在 phpMyAdmin 中运行它,但出现错误。也许还有另一种方式来编写此查询。 SELECT * FROM eat_eat_restaurants
我有 2 个列表(标题和数据值)。我想要将数据值列 1 匹配并替换为头文件列 1,以获得与 dataValue 列 1 和标题值列 2 匹配的值 头文件 TotalLoad,M0001001 Hois
我有两个不同长度的文件,file2 是一个很大的引用文件,我从中提取文件 1 的数据。 我有一行 awk,我通常会对其进行调整以在我的文件中进行查找和替换,但它总是在同一列中进行查找和替换。 所以对于
假设我有两个表,如下所示。 create table contract( c_ID number(1) primary key, c_name varchar2(50) not
我有一个带有 varchar 列的 H2 表,其检查约束定义如下: CONSTRAINT my_constraint CHECK (varchar_field <> '') 以下插入语句失败,但当我删
这是最少量的代码,可以清楚地说明我的问题: One Two Three 前 2 个 div 应该是 2 个左列。第三个应该占据页面的其余部分。最后,我将添加选项来隐藏和
在 Azure 中的 Log Analytics 中,我为 VM Heartbeat 选择一个预定义查询,我在编辑器中运行查询正常,但当我去创建警报时,我不断收到警报“查询未返回 TimeGenera
在 Azure 中的 Log Analytics 中,我为 VM Heartbeat 选择一个预定义查询,我在编辑器中运行查询正常,但当我去创建警报时,我不断收到警报“查询未返回 TimeGenera
今天我开始使用 JexcelApi 并遇到了这个:当您尝试从特定位置获取元素时,不是像您通常期望的那样使用sheet.getCell(row,col),而是使用sheet.getCell(col,ro
我有一个包含 28 列的数据库。第一列是代码,第二列是名称,其余是值。 public void displayData() { con.Open(); MySqlDataAdapter
我很沮丧:每当我缩小这个网页时,一切都变得一团糟。我如何将网页居中,以便我可以缩小并且元素不会被错误定位。 (它应该是 2 列,但所有内容都合并为 1)我试过 但由于某种原因,这不起作用。 www.o
我是一名优秀的程序员,十分优秀!