MYSQL的高级many2many查询

时间:2010-02-04 23:02:07

标签: php mysql select many-to-many

我正在尝试构建一个图像库,人们可以访问不同的组,并且小组决定允许他们查看哪些目录和图像。
我虽然很多2结构最适合这个。

到目前为止,我已经设法建立了这样的数据库:

image(image_name,image_file,image_id)
catalog(catalog_id,catalog_name)
供应商(supplier_id,supplier_name)
user(name,user_id)
image2cataloge(image_id,catalog_id)
image2supplier(image_id,supplier_id)
catalog2supplier(catalog_id,supplier_id)
user2supplier(user_id,supplier_id)

所以...据说,保存图像和制作供应商(或组织,如果你想),将用户添加到供应商并将图像链接到供应商和目录是没有问题的。插入没问题。
但是,根据用户供应商设置和目录选择正确的图像会更难。

例如,我有一个user_id 1的用户,可以访问supplier_id 1. supplier_id 1可以访问查看目录1,目录1保存带有image_id 1和2的图像。
但supplier_id 1只能访问image_id 2.
所有这些设置都存储在数据库中。如何进行选择查询?

这是我测试过的;

// $ catalog_id是我们所在的catalog_id // $ user_id是当前用户user_id

$sql = "SELECT i.*
FROM image i, user u, catalog cat, supplier s, supplier2user s2u, supplier2catalog s2c, image2catalog i2c, image2supplier i2s
WHERE u.id = '".$user_id."'
AND s2u.user_id = '".$user_id."'
AND s2u.supplier_id = s.id

AND s2c.catalog_id = '".$catalog_id."' 
AND i2c.catalog_id = '".$catalog_id."'

AND i2s.supplier_id = s.id
AND s2c.supplier_id = s.id

GROUP BY i.id
ORDER BY i.name ASC

但是当我添加了多个图像时,所有图像都显示在所有目录中。

编辑(2010/02/05):
哦,所以我已经想出如何在正确的目录中显示正确的图像。我通过以下方式做到这一点:

$sql = "SELECT i.*
    FROM 
        image i
    INNER JOIN image2catalog i2c

    ON i.id = i2c.image_id
    AND i2c.catalog_id = '".$pages_level_0[$i]['id']."'

    GROUP BY i.id
    ;";

这让我输出目前用户正在访问的目录中的正确图像。现在我只需要编辑此查询以过滤掉用户无权访问的所有图像。我非常感谢您提供的任何帮助!

编辑2010/02/09:
---

CREATION SCHEME

CREATE TABLE `user` (
  `id` int(11) NOT NULL auto_increment,
  `email` varchar(250) NOT NULL,
  `password` varchar(50) NOT NULL
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

CREATE TABLE `imagebank` (
      `id` int(11) NOT NULL auto_increment,
      `name` varchar(250) character set utf8 NOT NULL default '',
      `url` varchar(250) character set utf8 NOT NULL default '',
      `childof` varchar(250) character set utf8 NOT NULL default '',
      `hide` tinyint(4) NOT NULL,
      `publishdate` varchar(14) NOT NULL,
      `expiredate` varchar(14) NOT NULL,
      `editdate` varchar(14) NOT NULL,
      `editbygroup` varchar(250) NOT NULL,
      `openby` varchar(250) NOT NULL,
      `opendate` varchar(250) NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci;

    CREATE TABLE `imagebank_image` (
      `id` int(11) NOT NULL auto_increment,
      `name` varchar(250) NOT NULL,
      `img` varchar(250) NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

    CREATE TABLE `imagebank_image2catalog` (
      `image_id` int(11) NOT NULL,
      `catalog_id` int(11) NOT NULL,
      PRIMARY KEY  (`image_id`,`catalog_id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    CREATE TABLE `imagebank_image2supplier` (
      `image_id` int(11) NOT NULL,
      `supplier_id` int(11) NOT NULL,
      PRIMARY KEY  (`image_id`,`supplier_id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    CREATE TABLE `imagebank_supplier` (
      `id` int(11) NOT NULL auto_increment,
      `name` varchar(250) NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

    CREATE TABLE `imagebank_supplier2catalog` (
      `supplier_id` int(11) NOT NULL,
      `catalog_id` int(11) NOT NULL,
      PRIMARY KEY  (`supplier_id`,`catalog_id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

    CREATE TABLE `imagebank_supplier2user` (
      `supplier_id` int(11) NOT NULL,
      `user_id` int(11) NOT NULL,
      PRIMARY KEY  (`supplier_id`,`user_id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8;

有些数据:

INSERT INTO `imagebank` (`id`, `name`, `url`, `childof`, `hide`, `publishdate`, `expiredate`, `editdate`, `editbygroup`, `openby`, `opendate`) VALUES
(1, 'Test 1', 'test-1', '', 0, '20100204230233', '', '', '', '', ''),
(2, 'Test 2', 'test-2', '', 0, '20100204230244', '', '', '', '', '');

INSERT INTO `imagebank_image` (`id`, `name`, `img`) VALUES
(1, 'Test img 1', 'labb_9noq80bik5.jpeg'),
(2, 'Test img 2', 'labb_53626114dz.jpeg');

INSERT INTO `imagebank_image2catalog` (`image_id`, `catalog_id`) VALUES
(1, 1),
(2, 2);

INSERT INTO `imagebank_image2supplier` (`image_id`, `supplier_id`) VALUES
(1, 2),
(2, 1);

INSERT INTO `imagebank_supplier` (`id`, `name`) VALUES
(1, 'Supplier1'),
(2, 'Supplier2'),
(3, 'Supplier3');

INSERT INTO `imagebank_supplier2catalog` (`supplier_id`, `catalog_id`) VALUES
(1, 2),
(2, 1);

INSERT INTO `imagebank_supplier2user` (`supplier_id`, `user_id`) VALUES
(1, 1),
(1, 11),
(1, 12),
(2, 1),
(2, 10),
(3, 1);

INSERT INTO `user` (`id`, `email`, `password`) VALUES
(1, 'User1@test.com', 'ff02dd5s33taa2ba5ff7c2c4d3327e444'),
(10, 'User2@test.com', 'ff02dd5s33taa2ba5ff7c2c4d3327e444'),
(11, 'User3@test.com', 'ff02dd5s33taa2ba5ff7c2c4d3327e444'),
(12, 'User4@test.com', 'ff02dd5s33taa2ba5ff7c2c4d3327e444');
哇,现在有很多东西:P所以我知道桌子,特别是“目录”,我称之为“imagebank”可能看起来很奇怪。但我确实有我的理由,这不是真正的问题:)它是一个更大的图片的一部分。希望这可以帮助你帮助我。再次感谢。

1 个答案:

答案 0 :(得分:1)

如果您传递的是用户和目录ID,那么供应商无关紧要。

如果您在结果中需要供应商信息,那将是另一回事。

感觉您根本不应该让用户参与此查询,因为您似乎正在寻找特定供应商所拥有的目录中的图像。

如果是这种情况,那么我会在查询中删除用户ID的要求,而是使用供应商ID。

我假设用户已完成以下操作以达到启动此查询的程度:

  • 登录 - 显然:)
  • 点击'list suppliers'
  • 点击供应商
  • 点击目录

无论哪种方式,你都要做很多INNER JOIN。例如,检索给定用户的供应商列表的查询类似于

SELECT 
    s.supplier_id, 
    s.Supplier_name
FROM
    supplier s
INNER JOIN
    user u
INNER JOIN
    user2supplier u2s
ON
    u.user_id = u2s.user_id
ON
    u2s.supplier_id = s.supplier_id
WHERE
    u.user_id = 3 -- for example...

(现在,我还没有测试过SQL,但我认为这是正确的......)

如果我走在正确的轨道上,请告诉我 - 如果我有帮助,如果可以,我会很乐意提供更多帮助