postgresql - Postgres - 选择、排序和组合结果
问题描述
在我正在编写的应用程序中,当每个用户首次向服务器注册时,我会自动为他们生成一个“呼号”。呼号采用格式adjective adjective creature
。我从中选择这些值的基础 Postgres 表如下
CREATE TABLE adjectives ("adj" character varying(16) NOT NULL,"quality" smallint NOT NULL,
CONSTRAINT "adjectives_adj_key" UNIQUE ("adj")) WITH (oids = false);
INSERT INTO adjectives (adj,quality) VALUES ('bold',1),('witty',1),('red',5),('old',3);
CREATE TABLE creatures ("creature" character varying(16) NOT NULL,"quality" smallint NOT NULL,
CONSTRAINT "creatures_creature_key" UNIQUE ("creature")) WITH (oids = false);
INSERT INTO creatures (creature,quality) VALUES ('tiger',1),('dog',1),('sparrow',5),
('dolphin',3);
生成新呼号时,我需要执行以下操作
- 从各自的表格中随机选择两个形容词和一个生物
- 按质量升序排列形容词。为了尊重英语语法规则,我需要正确的形容词顺序。
Big Red Bull
,例如是对的。Red Big Bull
不是。 - 我需要检查生成的呼号是否已存在于如下所示的用户表中
CREATE TABLE users ("user" character varying(16) NOT NULL,"callsign CHARACTER VARYING(32) NOT NULL);
users 表还有很多其他内容 - 我已经修剪了细节。
虽然我可以使用基本的 SQL 选择并在服务器端脚本中完成其余的工作,但我怀疑有一种智能 SQL 唯一的方法来执行上述大部分(如果不是全部)以生成唯一的、语法上有效的呼号。我相当有限的 SQL 知识并不能胜任这项任务。如何才能做到这一点?
解决方案
编码此代码的最快方法是获取adjectives
X adjectives
X的笛卡尔积creatures
,删除已使用的那些,然后从列表中随机选择一个:
select concat(
a1.adj, ' ',
a2.adj, ' ',
c.creature
)
from adjectives a1
join adjectives a2
on a2.quality >= a1.quality
cross join creatures c
where not exists (select 1
from users
where callsign = concat(
a1.adj, ' ',
a2.adj, ' ',
c.creature))
order by random()
limit 1
;
如果您不想允许双倍adjective
值,则将不等式更改为>
而不是>=
。
如果您使用数百个adjectives
and creatures
,这将无法很好地扩展,但是除非我们将迭代引入解决方案,否则我无法想到如何避免笛卡尔积。
推荐阅读
- javascript - 未显示离子管道值
- php - php登录页面 - 当我插入有效数据时它不起作用,但是当我插入无效数据时它工作得很好
- javascript - 使用 npm prod 与 devq 进行编译
- c++ - 有没有办法避免以下代码中的内存泄漏?
- html - 网格布局 Internet Explorer 无法正常工作
- java - 我正在尝试使用 JAVA 从字符串中获取 URL
- python - 数值求解欧拉-拉格朗日方程的算法建议
- xml - 是否可以使用 XSLT 为值数组更新 XML?
- git - Git子模块在我不知道的情况下提交..?
- android - 如何使用 android studio 在地图内制作一个 clicable 圆圈