English 中文(简体)
在试图加入各种阵列时,按预期顺序加入
原标题:Subquery join not working as expected when trying to join an array
  • 时间:2024-02-16 10:38:45
  •  标签:
  • postgresql

我试图为用户设计一个询问,以便检索到其他用户尚未与之互动的其他用户。

解释如下:

create schema if not exists bv;

create table if not exists bv.user (
  id serial primary key,
  user_name varchar(15) not null,
  is_male boolean not null
);

create table if not exists bv.chat (
  id serial primary key
);

create table if not exists bv.chat_message (
  id serial primary key,
  chat_id bigint references bv.chat (id),
  user_id bigint references bv.user (id),
  message_text varchar(255) not null
);

create table if not exists bv.junction_user_chat (
  chat_id bigint references bv.chat (id),
  user_id bigint references bv.user (id)
);

create table if not exists bv.user_coordinates (
  id serial primary key,
  user_id bigint references bv.user (id)
);

create table if not exists bv.user_like (
  id serial primary key,
  source_user_id bigint references bv.user (id),
  target_user_id bigint references bv.user (id)
);
insert into bv.user values
  (100,  Mike , true),
  (101,  John , true),
  (102,  Jane , false),
  (103,  George , true),
  (104,  Lance , true);
insert into bv.chat values
  (10);
insert into bv.junction_user_chat values
  (10, 101),
  (10, 102);
insert into bv.chat_message values
  (500, 10, 101,  hello ),
  (501, 10, 102,  how are you? );
insert into bv.user_coordinates values
  (777, 100),
  (778, 101),
  (779, 102),
  (780, 103),
  (781, 104);
insert into bv.user_like values
  (1, 101, 102),
  (2, 102, 101),
  (3, 100, 102),
  (4, 103, 102),
  (5, 102, 104);

让我假设:user with ID 102 (Jane)。 我期待我回来,

┌──────┬────────────────────┬──────────┐
│ id   │ user_name          │ is_male  │
├──────┼────────────────────┼──────────┤
│ 100  │ Mike               │ true     │
│ 103  │ George             │ true     │
└──────┴────────────────────┴──────────┘

评论:

  • Users 102 and 101 already have a chat (and chat messages) between them, which why user 101 is not returned in the query,
  • User 102 does not exist as the source_user_id in bv."user_like" — if they did exist in that table, then user 103 would not be returned in the query
  • Users 100 and 103 are returned because,
    • they ve both "liked" user 102,
    • user 102 not exist as bv."user_like"."souce_user_id",
    • a chat doesn t exist for neither users 102 - 100 nor 102 - 103
  • User 104 is not returned because user 102 already "liked" them (even though user 104 hasn t liked user 102 back at the moment)

同样,这里的想法是让所有用户都了解,目前的用户(约102人)已经与用户进行了互动。 我通过“互动”是指<代码>bv user_lies>、bv chat>bv chat_message>上的记录。

我在此问:

SELECT DISTINCT ON (u.id)
    u.*
FROM bv.user_coordinates uc
JOIN bv.user u
    ON u.id = uc.user_id
JOIN (
    SELECT
      user_id,
      chat_id
    FROM bv.junction_user_chat
) chat_ids
  ON chat_ids.user_id = 102
LEFT JOIN bv.user_like ul
    ON u.id = ul.target_user_id
    AND ul.source_user_id = 102
LEFT JOIN bv.chat_message cm 
    ON cm.chat_id = any(chat_ids)
    AND (cm.user_id = u.id OR cm.user_id = 102)
WHERE u.id != 102
AND uc.user_id = u.id
AND u.is_male = true
AND ul.id is null
AND cm.id is null
GROUP BY u.id
ORDER BY u.id ASC

问题是,我不知道如何使用<条码>禁令_user_chat。 理想的情况是,我要形成一个阵列: ids(因为我已尝试这样做),然后检查用户代码<102<<>>>是否在场;如果是的话,我就想从结果中删除。

How can I get this to work, is my approach even in the correct direction? Postgres array methods and data types are new to me in general, I m much more used to junction tables, so I d much more prefer that over the current attempt with the nested join and ANY comparison.

最后,我要提到,这是实际查询的一个严重中下流的版本,因此,你看到了一个<条码>,从用户_coordinations<>/code>. 这一部分可以改变,但我在此保留。

问题回答

您能否尝试如下?

with chats_of_user as (
  select distinct chat_id
  from bv.user userA
  join bv.junction_user_chat chatA
  on userA.id = chatA.user_id
  where userA.id= 102
),
users_not_involed_in_chat as (
  select id
  from bv.user
  where bv.user.id NOT IN (
    select distinct userChatA.user_id
    from chats_of_user
    join bv.junction_user_chat userChatA
    on userChatA.chat_id = chats_of_user.chat_id
  )
),
not_liked_users as (
  select id
  from bv.user
  where id NOT IN (
    select distinct userLike.target_user_id
    from bv.user userA
    join bv.user_like userLike
    on userA.id = userLike.source_user_id
    where userA.id = 102

  ) 
)
select users_not_involed_in_chat.id
from users_not_involed_in_chat 
join not_liked_users
on users_not_involed_in_chat.id = not_liked_users.id
;

以上情况就是这样。 你可以广泛检查其他案件。 还请在使用<条码>解释分析后核对。

你可以总结一下这个问题:

  • getting the id of your chosen user
  • getting user_fans ids (people he is being liked from)
  • getting user_talkers ids (people he has talked to)
  • getting fans he has not talked to (user_fans except user_talkers)
  • retrieve user data for the remaining fans
WITH chosen_user AS (
    SELECT id AS user_id
    FROM bv.user
    WHERE user_name =  Jane 
), user_fans AS (
    SELECT source_user_id AS user_id
    FROM       bv.user_like 
    INNER JOIN chosen_user
            ON user_like.target_user_id = chosen_user.user_id
), user_talkers AS (
    SELECT user_chatters.user_id
    FROM       bv.junction_user_chat user_chats
    INNER JOIN chosen_user
            ON user_chats.user_id = chosen_user.user_id
    INNER JOIN bv.junction_user_chat user_chatters
            ON user_chatters.chat_id = user_chats.chat_id
    WHERE NOT user_chatters.user_id = chosen_user.user_id 
), fans_to_interact_with AS (
    SELECT * FROM user_fans
    EXCEPT ALL
    SELECT * FROM user_talkers
)
SELECT bv.user.*
FROM       fans_to_interact_with
INNER JOIN bv.user
        ON fans_to_interact_with.user_id = bv.user.id

Output:

id user_name is_male
100 Mike true
103 George true

查阅


如果您已经对选定的用户进行过滤,那么你就可以将这一解决办法简化为:

WITH user_fans AS (
    SELECT source_user_id AS user_id
    FROM bv.user_like 
    WHERE target_user_id = 102
), user_talkers AS (
    SELECT user_chatters.user_id
    FROM       bv.junction_user_chat user_chats
    INNER JOIN bv.junction_user_chat user_chatters
            ON user_chatters.chat_id = user_chats.chat_id
    WHERE user_chats.user_id = 102
      AND NOT user_chatters.user_id = 102
      
), fans_to_interact_with AS (
    SELECT * FROM user_fans
    EXCEPT ALL
    SELECT * FROM user_talkers
)
SELECT bv.user.*
FROM       fans_to_interact_with
INNER JOIN bv.user
        ON fans_to_interact_with.user_id = bv.user.id

查阅





相关问题
摘录数据

我如何将Excel板的数据输入我的Django应用? I m将PosgreSQL数据库作为数据库。

Postgres dump of only parts of tables for a dev snapshot

On production our database is a few hundred gigabytes in size. For development and testing, we need to create snapshots of this database that are functionally equivalent, but which are only 10 or 20 ...

How to join attributes in sql select statement?

I want to join few attributes in select statement as one for example select id, (name + + surname + + age) as info from users this doesn t work, how to do it? I m using postgreSQL.

What text encoding to use?

I need to setup my PostgreSQL DB s text encoding to handle non-American English characters that you d find showing up in languages such as German, Spanish, and French. What character encoding should ...

SQL LIKE condition to check for integer?

I am using a set of SQL LIKE conditions to go through the alphabet and list all items beginning with the appropriate letter, e.g. to get all books where the title starts with the letter "A": SELECT * ...

热门标签