2013-04-01 7 views
1

Мое веб-приложение требует наличия списка всех групп пользователей, членов группы и списка продуктов, к которым у них есть доступ, в зависимости от их членства в группе.MySQL Присоединение к нескольким таблицам

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

У меня есть следующий запрос:

SELECT u.id as user_id, u.username, ug.group_id, ug.group_name, u.firstname, u.surname, p.product_name, p.product_id, p.product_price, p.product_currency, p.is_public 
    FROM user_groups ug 
    LEFT JOIN user_group_users ugu ON ug.group_id = ugu.group_id 
    RIGHT JOIN users u ON u.id = ugu.user_id 
    LEFT JOIN user_group_product ugp on ug.group_id = ugp.group_id 
    LEFT JOIN product p on p.product_id = ugp.product_id 
    WHERE u.site_id = 5 
    ORDER BY ug.group_name desc, u.surname, u.firstname, u.username 

Это работает хорошо, и я конкатенации результаты с помощью PHP для доставки данных.

ВОПРОС: Таблица PRODUCTS также имеет is_public флаг, и я хотел бы, чтобы включить все продукты в наборе результатов, которые также имеют этот набор к 1, а также возвращенные продукты, которые пользователь имеет доступ к группе, но снова, только для этого сайта.

Итак, для ясности, я хотел бы вернуться:

  • Всех записей пользователей - независимо от того, если у них есть членство в группе (будет отображаться разгруппированные пользователи)
  • Всех записей пользователя с членством ассоциированной группы
  • Все группы
  • Все продукты - где пользователь является членом группы
  • Все продукты - где продукт устанавливается публике - is_public = 1

Все вышесказанное должно быть только для данного сайта.

UPDATE 3: Обновлено описание ТРЕБОВАНИЯМ

UPDATE 2: Таблицы структур:

-- 
-- Table structure for table `user_group_users` 
-- 

CREATE TABLE IF NOT EXISTS `user_group_users` (
    `user_group_id` bigint(20) unsigned NOT NULL auto_increment, 
    `user_id` mediumint(9) NOT NULL default '0', 
    `group_id` mediumint(9) NOT NULL default '0', 
    `created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`user_group_id`), 
    KEY `user_id` (`user_id`,`group_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=54 ; 

-- 
-- Table structure for table `user_groups` 
-- 

CREATE TABLE IF NOT EXISTS `user_groups` (
    `group_id` mediumint(8) unsigned NOT NULL auto_increment, 
    `site_id` mediumint(9) NOT NULL, 
    `group_name` varchar(100) NOT NULL default '', 
    `is_default` tinyint(1) NOT NULL COMMENT 'Users are automatically added to default groups at registration', 
    PRIMARY KEY (`group_id`), 
    KEY `site_id` (`site_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ; 

-- 
-- Table structure for table `user_group_product` 
-- 

CREATE TABLE IF NOT EXISTS `user_group_product` (
    `user_group_product_id` bigint(20) unsigned NOT NULL auto_increment, 
    `group_id` mediumint(9) NOT NULL default '0', 
    `product_id` mediumint(9) NOT NULL default '0', 
    `created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`user_group_product_id`), 
    KEY `product_id` (`product_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=124 ; 

-- 
-- Table structure for table `product` 
-- 

CREATE TABLE IF NOT EXISTS `product` (
    `product_id` mediumint(8) unsigned NOT NULL auto_increment, 
    `payment_enabled` tinyint(1) NOT NULL default '0', 
    `credit_enabled` tinyint(1) NOT NULL default '0', 
    `product_name` varchar(100) NOT NULL default 'Default Product', 
    `is_public` tinyint(1) NOT NULL default '1', 
    `product_price` decimal(10,2) default NULL, 
    `product_currency` varchar(5) default NULL, 
    PRIMARY KEY (`product_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ; 
+0

Вы пытались использовать 'INNER JOIN' вместо' LEFT' и 'RIGHT' и добавили это условие в предложение WHERE? –

+0

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

+0

@Mahmoud Gamal - Спасибо за предложение, однако я не сказал, что должен возвращать ВСЕ пользователей для сайта, даже если у них нет группового доступа, поскольку они будут иметь доступ к общедоступным продуктам, то есть is_public = 1. Я добавил это к исходному вопросу. – Ben

ответ

1

Если я правильно понял ваши требования, это должно работать:

SELECT u.id as user_id, u.username, ug.group_id, ug.group_name, u.firstname, u.surname, p.product_name, p.product_id, p.product_price, p.product_currency, p.is_public 
FROM user_groups ug 
JOIN user_group_users ugu ON ug.group_id = ugu.group_id 
JOIN users u ON u.id = ugu.user_id 
JOIN user_group_product ugp on ug.group_id = ugp.group_id 
JOIN product p on p.product_id = ugp.product_id 
WHERE u.site_id = 5 
UNION ALL 
SELECT u.id user_id, u.username, NULL group_id, NULL group_name, u.firstname, u.surname, p.product_name, p.product_id, p.product_price, p.product_currency, p.is_public 
FROM users 
CROSS JOIN product p 
WHERE p.is_public = 1 
ORDER BY 4 desc, 6, 5, 2 

- он должен возвращать все продукты, которые пользователи на сайте 5 имеют групповой доступ с, вместе со всеми общедоступными продуктами для всех пользователей.

+0

Большое спасибо Марк.Эта структура выглядит идеально, но набор результатов включает продукты других сайтов. Где-то сайт_id игнорируется, возможно, в UNION ALL SELECT. – Ben

+0

@Ben: У продуктов с других сайтов есть группы пользователей NULL и is_public = 1? Если это так, они включены, потому что вы просили все общедоступные продукты для всех пользователей? –

+0

@Ben: Пожалуйста, не делайте этого, хотя вы сделали несколько ссылок на продукты, являющиеся «с других сайтов» **, в вашей структуре данных нет ничего, что делает продукт специфичным для сайта **. Из того, что вы нам сказали, только ** пользователи ** являются специфическими для сайта. –

Смежные вопросы