SQL-запрос, чтобы выдавать правильные значки и размыть все остальное - PullRequest
0 голосов
/ 24 октября 2018

У меня есть таблица badges, в которой перечислены все доступные значки (badge_id, name, description, ...), таблица users, в которой перечислены все пользователи (user_id, name, ...) и таблица users_badges сохраняет все заработанные значки (id, badge_id, user_id).

Если пользователь 1 получает значок 5, запись (x, 5, 1) помещается в users_badges (пользователь может получить каждый значок только один раз).

Чтобы показать каждому пользователю, которыйЗначки, которые она заработала и которые до сих пор отсутствуют, я хочу перечислить все ее значки, в то время как заработанные значки являются цветными, а не заработанные значки серыми.

Для этого мне нужен соответствующий запрос SQL - и вот что яборюсь с.Возможным выводом будет отдельный список со всеми значками и рядом с ним user_id конкретного пользователя;или NULL, если она еще не заработала значок.

Первая попытка:

SELECT * FROM badges
LEFT JOIN users_badges ON badges.id = users_badges.badge_id
WHERE users_badges.user_id = ".$row['user_id']." OR users_badges.user_id IS NULL
ORDER BY badges.id

Проблема: это работает только для пользователя, которому принадлежат все значки других пользователей или более, посколькуГДЕ выбивает значки, принадлежащие только другим.

Вторая попытка:

SELECT * FROM badges
LEFT JOIN users_badges ON badges.id = users_badges.badge_id
ORDER BY badges.id

Проблема: значки перечислены несколько раз, если они принадлежат нескольким пользователям.Добавление DISTINCT не решило бы проблему, поскольку строки уже различны (разные идентификаторы пользователей).Возможно, можно пойти из этого подхода и выбросить все строки с user_id с, кроме запрошенного, но только если она уже заработала для значка (чтобы гарантировать, что все не принадлежащие значки также перечислены (серым цветом))?

Большое спасибо!

1 Ответ

0 голосов
/ 24 октября 2018

Делая некоторые предположения о структуре ваших данных, я создал фиктивные таблицы для этого примера:

create table #badges
(
    badge_id int,
    [name] varchar(50),
    [description] varchar(50)
)

create table #users
(
    [user_id] int,
    [name] varchar(50)
)

create table #users_badges
(
    id int,
    badge_id int,
    [user_id] int
)

insert into #badges
values
    (1,'Starter Badge','It''s your first time.'),
    (2,'Rookie Badge','You''re just getting started.'),
    (3,'Intermediate Badge','Now you''re starting to get the hang of this.'),
    (4,'Expert Badge','You are a master!')

insert into #users
values
    (1,'John Smith'),
    (2,'Alice Johnson'),
    (3,'Phillip Black'),
    (4,'Sarah Goodwell'),
    (5,'Ian Hunter')

insert into #users_badges
values
    (1,1,1),
    (2,1,2),
    (3,1,3),
    (4,1,4),
    (5,2,1),
    (6,2,2),
    (7,2,4),
    (8,3,5),
    (9,4,1),
    (10,4,2)

Я думаю, что это результат, который вы ищете (здесь, в частности, на пользователя сuser_id из 1 - Джон Смит):

select 
    b.*,  
    case when ub.id is not null then 'Earned' else null end as badgeStatus
from #badges b
left join #users_badges ub on b.badge_id = ub.badge_id and ub.[user_id] = 1

Здесь перечислены все значки и показано, какие из них Джон заработал:

/------------------------------------------------------------------------|--------\
| id | name               | description                                  | status |
|----|--------------------|----------------------------------------------|--------|
|  1 | Starter Badge      | It's your first time.                        | Earned |
|  2 | Rookie Badge       | You're just getting started.                 | Earned |
|  3 | Intermediate Badge | Now you're starting to get the hang of this. | NULL   |
|  4 | Expert Badge       | You are a master!                            | Earned |
\---------------------------------------------------------------------------------/
...