我有一个这种布局的表:
CREATE TABLE Favorites
(
FavoriteId uuid NOT NULL PRIMARY KEY,
UserId uuid NOT NULL,
RecipeId uuid NOT NULL,
MenuId uuid
)
Run Code Online (Sandbox Code Playgroud)
我想创建一个类似于此的唯一约束:
ALTER TABLE Favorites
ADD CONSTRAINT Favorites_UniqueFavorite UNIQUE(UserId, MenuId, RecipeId);
Run Code Online (Sandbox Code Playgroud)
但是,这将允许多行具有相同的(UserId, RecipeId)if MenuId IS NULL.我想允许NULL在MenuId存储不具有关联菜单中的最爱,但我只希望每个用户/食谱对这些行中最多只有一个.
我到目前为止的想法是:
使用一些硬编码的UUID(例如全零)而不是null.
但是,MenuId每个用户的菜单都有一个FK约束,所以我必须为每个用户创建一个特殊的"空"菜单,这是一个麻烦.
使用触发器检查是否存在空条目.
我认为这是一个麻烦,我喜欢尽可能避免触发器.另外,我不相信他们能保证我的数据永远不会处于不良状态.
只需忘记它并检查中间件或插入函数中是否存在空条目,并且没有此约束.
我正在使用Postgres 9.0.
我有什么方法可以忽略吗?
以下是最简单的可能示例,但任何解决方案都应该能够扩展到需要的n个顶级结果:
根据下面的表格,使用人员,组和年龄列,您将如何获得每组中最老的2个人?(组内的关系不应该产生更多结果,但按字母顺序给出前2个)
+--------+-------+-----+ | Person | Group | Age | +--------+-------+-----+ | Bob | 1 | 32 | | Jill | 1 | 34 | | Shawn | 1 | 42 | | Jake | 2 | 29 | | Paul | 2 | 36 | | Laura | 2 | 39 | +--------+-------+-----+
期望的结果集:
+--------+-------+-----+ | Shawn | 1 | 42 | | Jill | 1 | 34 | | Laura | 2 | 39 | | …
由于Postgres能够进行LATERAL连接,我一直在阅读它,因为我目前为我的团队执行复杂的数据转储,其中包含大量低效的子查询,这使得整个查询需要四分钟或更长时间.
我知道LATERAL联接可能能够帮助我,但即使在阅读了像Heap Analytics 这样的文章之后,我仍然没有完全遵循.
LATERAL加入的用例是什么?LATERAL连接和子查询之间有什么区别?
这是一个简化的表结构:
TABLE products (
product_id INT (primary key, auto_increment),
category_id INT,
product_title VARCHAR,
etc
);
TABLE product_photos (
product_photo_id (primary key, auto_increment),
product_id INT,
photo_href VARCHAR,
photo_order INT
);
Run Code Online (Sandbox Code Playgroud)
一个产品可以有多张照片,每张产品的第一张产品照片(基于photo_order)是默认照片.
现在,我只需要产品详细信息页面上的所有照片,但在我列出多个产品的页面上,例如产品目录页面,我只想显示默认照片.
所以我要做的是查询产品列表,包括每个产品的默认照片.
这显然不起作用,它将返回所有照片与每张照片的产品信息重复:
SELECT p.*, ph.*
FROM products AS p
LEFT JOIN product_photos AS ph
ON p.product_id=ph.product_id
ORDER BY p.product_title ASC
Run Code Online (Sandbox Code Playgroud)
我需要弄清楚如何做这样的事情,但我不知道语法(或者是否可能)
SELECT p.*, ph.*
FROM products AS p
LEFT JOIN product_photos AS ph
ON p.product_id=ph.product_id **ORDER BY ph.photo_order ASC LIMIT 1**
ORDER BY p.product_title ASC
Run Code Online (Sandbox Code Playgroud)
编辑:我在下面的答案帮助下找到了解决方案,谢谢大家!
SELECT p.*, ph.* …Run Code Online (Sandbox Code Playgroud)