简体   繁体   English

Postgresql 左连接问题

[英]Postgresql left join issue

I have two tables我有两张桌子

create table sources (
    user_id bigint,
    source varchar,
    created timestamp default now(),
    unique(user_id, source)
)
create table subscriptions (
    user_id bigint unique primary key,
    plan int not null references plans(id),
    starts timestamp default now(),
    ends timestamp default now() + interval '30' day
)

I try to select everything from sources when user has active subscription, I use this query当用户有活动订阅时,我尝试从源中选择所有内容,我使用此查询

SELECT src.* FROM sources AS src LEFT JOIN subscriptions as sub ON sub.user_id=src.user_id WHERE now() < sub.ends

However, it does not return all data, the problem became clear when I tried但是,它并没有返回所有数据,当我尝试时问题变得清晰

SELECT * FROM sources AS src LEFT JOIN subscriptions as sub ON sub.user_id=src.user_id

What may be the problem and how itspossible for me to get this info in the other way?可能是什么问题以及我如何以其他方式获取此信息? PS subscriptions table has rows with other user_id's. PS 订阅表包含其他 user_id 的行。 Thank you very much!非常感谢! 第二个 sql 查询的输出

UPDATE更新

Your left join is working.您的left join正在工作。 If your image is of SELECT * FROM sources AS src LEFT JOIN subscriptions as sub ON sub.user_id=src.user_id then some of your users have no subscriptions.如果您的图像是SELECT * FROM sources AS src LEFT JOIN subscriptions as sub ON sub.user_id=src.user_id那么您的一些用户没有订阅。

SELECT * FROM sources AS src LEFT JOIN subscriptions ... only ensures every matching row in sources will be fetched regardless of whether it has a matching row in subscriptions . SELECT * FROM sources AS src LEFT JOIN subscriptions ...只确保sources每个匹配行都将被获取,而不管它在subscriptions中是否有匹配的行。


[I wrote the rest when I thought it was a different problem, but the advice remains.] [当我认为这是一个不同的问题时,我写了其余的,但建议仍然存在。]

This is possible because sources.user_id is not set up as a foreign key so the database cannot enforce referential integrity .这是可能的,因为sources.user_id未设置为外键,因此数据库无法强制执行参照完整性 As far as the database is concerned, sources.user_id is just some number.就数据库而言, sources.user_id只是一些数字。 If you delete a user, their sources and subscriptions will hang around.如果您删除一个用户,他们的来源和订阅将继续存在。

In general...一般来说...

  • Clever primary keys just bring complications.聪明的主键只会带来并发症。 Give everything more complicated than a simple join table id bigserial primary key and be done with it.提供比简单的连接表id bigserial primary key更复杂的所有内容并完成它。
  • Declare everything not null unless you have a good reason it should be null.除非您有充分的理由将其声明为not null否则将所有内容声明not null null。
  • Use on delete cascade to clean up when a user is deleted, but see below. on delete cascade上使用以在用户被删除时进行清理,但请参见下文。
create table sources (
    id bigserial primary key,

    -- When a user is deleted, its sources will also be deleted
    user_id bigint not null references users(id) on delete cascade,

    source varchar not null,
    created timestamp not null default now(),

    unique(user_id, source)
)

create table subscriptions (
    id bigserial primary key,

    -- When a user is deleted, its subscriptions will also be deleted
    user_id bigint not null unique references foreign key users(id) on delete cascade,

    -- Make foreign key names consistent, and use a consistent type for ids.
    plan_id bigint not null references plans(id) on delete cascade,

    starts timestamp not null default now(),
    ends timestamp not null default now() + interval '30' day
)

Whether to use on delete cascade when a deleted user still has sources and subscriptions depends on how you want to handle that situation.当被删除的用户仍然拥有源和订阅时,是否使用on delete cascade取决于您希望如何处理这种情况。 You might want to prevent deleting a user which still has active sources and subs, in which case leave off on delete cascade and handle cleaning up the user's sources and subs manually.您可能希望阻止删除仍具有活动源和子项的用户,在这种情况下,请停止on delete cascade并手动清理用户的源和子项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM