英文:
SELECT rows with primary key of multiple columns
问题
如何根据提供的一对列表选择所有相关记录?
表格:
CREATE TABLE "users_groups" (
"user_id" INTEGER NOT NULL,
"group_id" BIGINT NOT NULL,
PRIMARY KEY (user_id, group_id),
"permissions" VARCHAR(255)
);
例如,如果我有以下JavaScript array
,我应该从数据库中获取这些数据:
[
{user_id: 1, group_id: 19},
{user_id: 1, group_id: 11},
{user_id: 5, group_id: 19}
]
在这里,我们可以看到相同的 user_id
可能属于多个组。
我可以使用 for-loop
遍历每个数组元素并创建以下 查询:
SELECT * FROM users_groups
WHERE (user_id = 1 AND group_id = 19)
OR (user_id = 1 AND group_id = 11)
OR (user_id = 5 AND group_id = 19);
但这是否是最佳解决方案?假设数组非常长。据我所知,查询长度可能会达到约 1GB。
有什么最佳和快速的解决方案吗?
英文:
How do I select all relevant records according to the provided list of pairs?
table:
CREATE TABLE "users_groups" (
"user_id" INTEGER NOT NULL,
"group_id" BIGINT NOT NULL,
PRIMARY KEY (user_id, group_id),
"permissions" VARCHAR(255)
);
For example, if I have the following JavaScript array
of pairs that I should get from DB
[
{user_id: 1, group_id: 19},
{user_id: 1, group_id: 11},
{user_id: 5, group_id: 19}
]
Here we see that the same user_id
can be in multiple groups.
I can pass with for-loop
over every array element and create the following query:
SELECT * FROM users_groups
WHERE (user_id = 1 AND group_id = 19)
OR (user_id = 1 AND group_id = 11)
OR (user_id = 5 AND group_id = 19);
But is this the best solution? Let say if the array is very long. As I know query length may get ~1GB.
what is the best and quick solution to do this?
答案1
得分: 2
Bill Karwin的回答在Postgres中同样有效。
然而,我有这样的经验,与VALUES子句连接往往比大型IN列表(具有数百甚至数千个元素)更快:
select ug.*
from user_groups ug
join (
values (1,19), (1,11), (5,19), ...
) as l(uid, guid) on l.uid = ug.user_id and l.guid = ug.group_id;
这假设提供的值中没有重复项,否则JOIN将导致重复的行,而IN解决方案不会这样做。
英文:
Bill Karwin's answer will work for Postgres just as well.
However, I have made the experience that joining against a VALUES clause is very often faster than a large IN list (with hundreds if not thousands of elements):
select ug.*
from user_groups ug
join (
values (1,19), (1,11), (5,19), ...
) as l(uid, guid) on l.uid = ug.user_id and l.guid = ug.group_id;
This assumes that there are no duplicates in the values provided, otherwise the JOIN would result in duplicated rows, which the IN solution would not do.
答案2
得分: 1
你同时标记了mysql和postgresql,所以我不知道你实际使用哪个SQL数据库。
至少MySQL支持元组比较:
SELECT * FROM users_groups WHERE (user_id, group_id) IN ((1,19), (1,11), (5,19), ...)
这种谓词可以在MySQL 5.7及更高版本中进行优化。请参阅https://dev.mysql.com/doc/refman/5.7/en/range-optimization.html#row-constructor-range-optimization
我不知道PostgreSQL是否支持这种类型的谓词,或者是否对其进行了优化。
英文:
You tagged both mysql and postgresql, so I don't know which SQL database you're really using.
MySQL at least supports tuple comparisons:
SELECT * FROM users_groups WHERE (user_id, group_id) IN ((1,19), (1,11), (5,19), ...)
This kind of predicate can be optimized in MySQL 5.7 and later. See https://dev.mysql.com/doc/refman/5.7/en/range-optimization.html#row-constructor-range-optimization
I don't know whether PostgreSQL supports this type of predicate, or if it optimizes it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论