Выбор строк из таблицы на основе результатов из других таблиц в Mysql и PDO - PullRequest
0 голосов
/ 13 июля 2010

Я вроде как в тупике.

У меня есть таблица элементов с полями: ID, заголовок, create_by, группа .

У меня также есть другая таблица групп с полями: ID, create_by, group_name
и окончательная таблица пользователей с полями: ID, имя пользователя, пароль и т. д. .

Идея состоит в том, что этот пользователь может видеть только элементы, созданные вошедшим в систему пользователем, или элементы, в которых зарегистрированный пользователь является частью группы пользователей элемента.

Каждый пользователь может входить в неопределенное количество групп, и каждая группа может содержать неопределенное количество пользователей.

Единственный способ на данный момент, когда я могу думать об этом, - иметь отдельную таблицу для каждого пользователя (перечисляя все группы, членами которых они являются).

Затем я сначала ищу в таблице предметов предметы, созданные вошедшим в систему пользователем.
Во-вторых, выполните поиск в таблице «групп» этого пользователя, чтобы найти идентификаторы каждой группы, к которой он принадлежит, а затем снова рекурсивно выполните поиск в таблице элементов и загрузите каждый элемент, где текущий найденный идентификатор_группы соответствует идентификатору группы элемента.

Я знаю, что это будет работать, если правильно кодировать для небольшого числа элементов, групп и / или пользователей, но я подозреваю, что каждая страница будет загружаться / обрабатывать большие таблицы. Также кажется довольно грязным иметь новую таблицу для каждого пользователя, учитывая, что у вас могут быть тысячи пользователей и, следовательно, тысячи таблиц.

Я подозреваю, что объединение таблиц может обеспечить решение, но я не очень понимаю, как в данный момент. Если это так, я очень рад переименовать поля таблицы, чтобы добиться этого.

Мой текущий код для получения предметов таков (я знаю, что это, вероятно, не идеально):

$query = "SELECT * FROM items WHERE user_id=:u_id";
$stmt = $conn->prepare($query);
$stmt->execute(array(':u_id'=>$_SESSION['u_id']));
$exist = '<option></option>';
while( $uRow = $stmt->fetch() ) {
    $exist .= '<option value="'.$uRow['id'].'">'.$uRow['title'].'</option>';
}
$user_groups_tbl = "user_groups_".$_SESSION['u_id'];
$query1 = "SELECT * FROM $user_groups_tbl";
$query2 = "SELECT * FROM items WHERE group_id=:group";
$stmt1 = $conn->prepare($query1);
$stmt2 = $conn->prepare($query2);
$stmt1->execute();
while( $gRow = $stmt1->fetch() ) {      
    $stmt2->execute(array(':group'=>$gRow['group_id']));
    while( $row = $stmt2->fetch() ) {
        if( $row['user_id'] !== $_SESSION['u_id'] ) {
            $exist .= '<option value="'.$uRow['id'].'">'.$uRow['title'].'</option>';
        }
    }
}
 return $exist;  

Я надеюсь, что мои потребности и намерения ясны. Любая помощь будет оценена.

Ответы [ 3 ]

3 голосов
/ 13 июля 2010

Единственный способ на данный момент, когда я могу думать об этом, - иметь отдельную таблицу для каждого пользователя (перечисляя все группы, членами которых они являются).

Yikes!Не делай этого!Давайте воссоздадим ваши таблицы, используя небольшую нормализацию.

-- Our users
CREATE TABLE users (
    user_id INTEGER PRIMARY KEY,
    ...
);

-- And our groups
CREATE TABLE groups (
    group_id INTEGER PRIMARY KEY,
    ...
);

-- New!  A list of all groups and the users that belong to them.
-- This is also conveniently a list of users and the groups that they belong to.
CREATE TABLE group_users (
    user_id INTEGER REFERENCES users(user_id),
    group_id INTEGER REFERENCES groups(group_id),
    UNIQUE KEY(user_id, group_id)
);

-- Finally, our mysterious "items"
CREATE TABLE items (
    item_id ...,
    title ...,
    user_id INTEGER REFERENCES users(user_id),
    group_id INTEGER REFERENCES groups(group_id)
);

Учитывая:

Идея состоит в том, что только элементы, созданные зарегистрированным пользователем, или элементы, в которых зарегистрированный пользовательэтот пользователь может видеть часть пользовательской группы элемента.

SELECT *
  FROM items
 WHERE items.user_id = ?
    OR items.group_id IN(
           SELECT group_id
             FROM group_users
            WHERE user_id = ?
       )

Это должно захватить все элементы, созданные пользователем, а также все элементы, входящие в группу, к которой принадлежит пользователь.к.(Примечание. Этот запрос может не оптимизироваться должным образом в зависимости от версии MySQL. Возможно, вам потребуется преобразовать подзапрос в предложении WHERE, чтобы он вместо этого был в предложении FROM.)

2 голосов
/ 13 июля 2010

Эй, Дрент, это отличный вопрос. Как вы упомянули, стандартный способ справиться с отношением «многие ко многим» (от многих пользователей ко многим группам) - это использование таблицы соединений. Вот таблицы:

  • элементы : идентификатор, название, созданный_бай, идентификатор_группы
  • групп : ID, созданный_бай, имя_группы
  • пользователи : идентификатор, имя пользователя, пароль и т. Д.
  • и только одна новая таблица - users_groups : user_ID, group_ID

Теперь, когда пользователь присоединяется к группе, просто добавьте строку в таблицу user_group. Например, если пользователь 327 присоединяется к группе 14:

INSERT INTO users_groups SET user_ID=327, group_ID=14;

Чтобы отобразить все элементы, к которым пользователь может получить доступ:

SELECT * FROM items
JOIN users_groups ON users_groups.group_ID = items.group_ID
WHERE users_groups.user_ID = :user

Обязательно замените :user идентификатором текущего пользователя. Кроме того, я не могу использовать те же имена столбцов, что и в ваших таблицах, поэтому будьте осторожны.

Чтобы получить список групп, в которые входит пользователь:

SELECT * FROM groups
JOIN users_groups ON users_groups.group_ID = groups.ID
WHERE users_groups.user_ID = :user
1 голос
/ 13 июля 2010

Отношения (я думаю), которые вы ищете, называются «есть и принадлежит многим» или HABTM.Вам понадобится так называемая сводная таблица с feilds user_id и group_id.

Тогда, если у вас есть пользователь, вы можете найти все group_id, с которыми связан user_id.Затем вы можете использовать это, чтобы найти предметы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...