2013-04-01 147 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:請不要指出,雖然您已經對「來自其他網站」的產品進行了大量的引用,但是您的數據結構中沒有任何內容會針對某個網站製作產品**。從您告訴我們的信息來看,只有**用戶**是特定於某個網站的。 –