2013-04-01 191 views
1

我的web应用程序需要根据其组成员资格列出所有用户组,成员以及他们有权访问的产品列表。MySQL跨多个表加入

该Web应用程序支持多个“网站”;一个网站是这些用户,群组和产品的唯一标识符。

我有以下查询:

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

以上所有内容仅适用于相关网站。

更新3:表结构:质量要求

更新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

非常感谢马克。这种结构看起来很理想,但结果集包括其他网站的产品。在某处,site_id被忽略,​​可能在UNION ALL SELECT中。 – Ben

+0

@Ben:其他网站的产品是否有NULL用户组,is_public = 1?如果是这样,他们被包括在内,因为你要求为所有用户提供所有公共产品? –

+0

@Ben:请不要指出,虽然您已经对“来自其他网站”的产品进行了大量的引用,但是您的数据结构中没有任何内容会针对某个网站制作产品**。从您告诉我们的信息来看,只有**用户**是特定于某个网站的。 –