McFree
@McFree
JS, TS, C#

Как показать только те данные, которые отсутствуют в связи?

Есть проблема, создаю кастомный модуль с новостями и оповещением о новых новостях соответственно. Работаю с базой PostgreSQL.
Создал 2 таблицы:
news
id - AI Int
title	- Short String
description - Text
shortDescription - String
status - Int (Enum 1\2\3)
createdAt - Timestamp
updatedAt - Timestamp
groupId - Int
teamId - Int
blockId - Int
lang - Short String


И вторая
id - AI Int
newsId - Index News.id
userId - Index User.id
readedAt - Timestamp


Создав 10 новостей под разные условия делаю запрос на получение:
SELECT 
"news"."id" AS "news_id", 
"news"."title" AS "news_title", 
"news"."description" AS "news_description", 
"news"."shortDescription" AS "news_shortDescription", 
"news"."status" AS "news_status", 
"news"."createdAt" AS "news_createdAt", 
"news"."updatedAt" AS "news_updatedAt", 
"news"."teamId" AS "news_teamId", 
"news"."groupId" AS "news_groupId", 
"news"."blockId" AS "news_blockId", 
"news"."lang" AS "news_lang" 
FROM 
"news" "news" 
LEFT JOIN 
"readed_news" "rn" 
ON 
"rn"."userId" = 5 
WHERE 
"news"."id" != "rn"."newsId" AND 
"news"."status" = 2 AND 
"news"."lang" = 'ru' AND 
"news"."blockId" = 0 AND 
"news"."groupId" = 0 AND 
"news"."teamId" = 0


Но результатом этого запроса приходят все новости, которые имеют связку со второй таблицей и которые не сущестуют, которые имеют значение status = 2, другие условия работают отлично, кроме проверки отсутвия самой связи со второй таблице

Экспорты для понимания ситуации:
spoiler
INSERT INTO "news" ("id", "title", "description", "shortDescription", "status", "createdAt", "updatedAt", "groupId", "teamId", "blockId", "lang") VALUES
(1,	'Forward Security Officer',	'Central',	'Product',	2,	'2020-11-30 12:27:18.047',	'2020-11-30 12:27:18.047',	0,	0,	0,	'ru'),
(4,	'National Infrastructure Representative',	'Investor',	'Investor',	1,	'2020-11-30 13:59:11.584078',	'2020-11-30 13:59:11.584078',	1,	0,	0,	'ru'),
(3,	'Customer Accountability Administrator',	'Human',	'Central',	2,	'2020-11-30 13:57:38.231',	'2020-11-30 13:57:38.231',	0,	1,	0,	'ru'),
(5,	'International Intranet Manager',	'Global',	'National',	2,	'2020-11-30 14:01:30.907',	'2020-11-30 14:01:30.907',	0,	0,	1	'ru'),
(6,	'Dynamic Infrastructure Planner',	'National',	'Principal',	2,	'2020-11-30 14:01:45.809',	'2020-11-30 14:01:45.809',	0,	0,	0,	'ru'),
(7,	'Forward Paradigm Administrator',	'District',	'Dynamic',	2,	'2020-11-30 14:02:01.172',	'2020-11-30 14:02:01.172',	0,	0,	0,	'ru'),
(8,	'Forward Assurance Orchestrator',	'Regional',	'Dynamic',	2,	'2020-11-30 14:02:13.705',	'2020-11-30 14:02:13.705',	0,	0,	0,	'ru'),
(9,	'National Integration Director',	'Customer',	'Investor',	2,	'2020-11-30 14:02:25.933',	'2020-11-30 14:02:25.933',	0,	0,	0,	'ru');

INSERT INTO "readed_news" ("id", "newsId", "userId", "readedAt") VALUES
(1,	1,	5,	'2020-11-30 12:39:40.445662'),
(2,	2,	5,	'2020-11-30 13:46:27.55037');
  • Вопрос задан
  • 55 просмотров
Решения вопроса 1
@galaxy
LEFT JOIN делается так:
...
LEFT JOIN "readed_news" "rn" 
ON ("rn"."newsId" = "news"."id" )
...


Тогда, если в таблице связи readed_news новости нет, в колонке rn.newsId будет NULL (можно добавить в WHERE: AND rn.newsId IS NULL).
Или обойдитесь без джойна и сделайте в WHERE:
...
AND id NOT IN (
  SELECT newsId FROM readed_news WHERE userId = 5
)


(под капотом, конечно, все равно будет джойн).
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@MaximaXXl
Используйте not in или not exists
если не разберетесь - напишите, я добавлю select
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы