MySQL多表连接

时间:2011-06-11 17:18:59

标签: php mysql sql join

予。简介

我正在建立一个支持系统,来自某个国家/地区的用户会针对某个类别提出问题,并且来自该国家/地区,行政部门和类别的专家会被分配该问题。

E.x。来自国家Germany且邮政编码为1000的用户在类别Software上出现问题。来自国家Germany和/或邮政编码边界MIN_PROVINCE_ZIPCODE <= 1000 >= MAX_PROVINCE_ZIPCODE的省/和/或邮政编码边界MIN_REGION_ZIPCODE <= 1000 >= MAX_REGION_ZIPCODE和类别Software的区域的专家会被分配问题。< / p>

即: 选择问题国家/地区等于专家国家/地区的所有问题,并且问题类别等于专家类别之一,和/或问题邮政编码大于或等于最小省份邮政编码且小于或等于最大省邮政编码,以及/或发行邮政编码大于或等于区域最小邮政编码,发行代码小于或等于邮政编码。

“和/或”表示如果指派专家从特定行政区划中提出问题,如果不是,则为他们分配与其国家和类别相匹配的所有内容

II。数据库模式&amp;记录

*请记住!*

a)专家可以参与......

  1. 一个,多个或没有类别
  2. 一个,多个或没有省
  3. 一个,多个或没有区域
  4. b)如果专家的一部分......

    1. 一个类别,然后不会向他们分配任何问题
    2. 一个省,然后将为他们的国家和类别分配所有问题
    3. 一个地区,然后将为他们的省份分配所有问题
    4. 1。模式

      CREATE TABLE IF NOT EXISTS `categories` (
        `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
        `name` varchar(300) NOT NULL,
        PRIMARY KEY (`id`)
      ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
      
      CREATE TABLE IF NOT EXISTS `provinces` (
        `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
        `country` varchar(300) NOT NULL,
        `province` varchar(300) NOT NULL,
        `min_zipcode` int(5) unsigned NOT NULL,
        `max_zipcode` int(5) unsigned NOT NULL,
        PRIMARY KEY (`id`)
      ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
      
      CREATE TABLE IF NOT EXISTS `regions` (
        `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
        `provinceid` int(11) unsigned NOT NULL,
        `region` varchar(300) NOT NULL,
        `min_zipcode` int(5) unsigned NOT NULL,
        `max_zipcode` int(5) unsigned NOT NULL,
        PRIMARY KEY (`id`)
      ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
      
      CREATE TABLE IF NOT EXISTS `issues` (
        `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT,
        `categoryid` int(11) unsigned NOT NULL,
        `country` varchar(150) NOT NULL,
        `zipcode` int(5) NOT NULL,
        PRIMARY KEY (`id`)
      ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
      
      CREATE TABLE IF NOT EXISTS `experts` (
        `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
        `country` varchar(150) NOT NULL DEFAULT 'none',
        PRIMARY KEY (`id`)
      ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
      
      CREATE TABLE IF NOT EXISTS `experts_categories` (
        `expertid` int(11) unsigned NOT NULL,
        `categoryid` int(11) unsigned NOT NULL,
        PRIMARY KEY (`expertid`,`categoryid`)
      ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
      
      CREATE TABLE IF NOT EXISTS `experts_provinces` (
        `expertid` int(11) unsigned NOT NULL,
        `provinceid` int(11) unsigned NOT NULL,
        PRIMARY KEY (`expertid`,`provinceid`)
      ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
      
      CREATE TABLE IF NOT EXISTS `experts_regions` (
        `expertid` int(11) NOT NULL,
        `regionid` int(11) NOT NULL,
        PRIMARY KEY (`expertid`,`regionid`)
      ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
      

      2。记录

      INSERT INTO `categories` (`id`, `name`) VALUES
      (1, 'Software'),
      (2, 'Hardware');
      
      INSERT INTO `experts` (`id`, `country`) VALUES
      (1, 'Germany'),
      (2, 'France'),
      (3, 'Germany');
      
      INSERT INTO `experts_categories` (`expertid`, `categoryid`) VALUES
      (1, 1),
      (1, 2),
      (2, 1),
      (3, 1);
      
      INSERT INTO `experts_provinces` (`expertid`, `provinceid`) VALUES
      (1, 4),
      (2, 6),
      (2, 7);
      
      INSERT INTO `experts_regions` (`expertid`, `regionid`) VALUES
      (1, 8),
      (1, 10);
      
      INSERT INTO `issues` (`id`, `categoryid`, `country`, `zipcode`) VALUES
      (1, 2, 'Germany', 2100),
      (2, 1, 'France', 1900),
      (3, 1, 'Germany', 1500),
      (4, 2, 'Germany', 2800),
      (5, 2, 'France', 1850);
      
      INSERT INTO `provinces` (`id`, `country`, `province`, `min_zipcode`, `max_zipcode`) VALUES
      (1, 'Germany', 'Province One', 1000, 1299),
      (2, 'Germany', 'Province Two', 1300, 1499),
      (3, 'Germany', 'Province Three', 1500, 1999),
      (4, 'Germany', 'Province Four', 2000, 2899),
      (5, 'France', 'Province One', 1000, 1799),
      (6, 'France', 'Province Two', 1800, 2199),
      (7, 'France', 'Province Three', 2200, 2399);
      
      INSERT INTO `regions` (`id`, `provinceid`, `region`, `min_zipcode`, `max_zipcode`) VALUES
      (1, 1, 'Region One', 1000, 1099),
      (2, 1, 'Region Two', 1100, 1159),
      (3, 1, 'Region Three', 1160, 1299),
      (4, 2, 'Region One', 1300, 1400),
      (5, 2, 'Region Two', 1401, 1499),
      (6, 3, 'Region One', 1500, 1699),
      (7, 3, 'Region Two', 1700, 1999),
      (8, 4, 'Region One', 2000, 2299),
      (9, 4, 'Region Two', 2300, 2599),
      (10, 4, 'Region Three', 2600, 2699),
      (11, 4, 'Region Four', 2700, 2899),
      (12, 5, 'Region One', 1000, 1699),
      (13, 5, 'Region Two', 1700, 1799),
      (14, 6, 'Region One', 1800, 2000),
      (15, 6, 'Region Two', 2001, 2199),
      (16, 7, 'Region One', 2200, 2299),
      (17, 7, 'Region Two', 2300, 2399);
      

      3。可视化架构

      mysql> DESC `categories`;
      +-------+------------------+------+-----+---------+----------------+
      | Field | Type             | Null | Key | Default | Extra          |
      +-------+------------------+------+-----+---------+----------------+
      | id    | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
      | name  | varchar(300)     | NO   |     | NULL    |                |
      +-------+------------------+------+-----+---------+----------------+
      
      mysql> DESC `provinces`;
      +-------------+---------------------+------+-----+---------+----------------+
      | Field       | Type                | Null | Key | Default | Extra          |
      +-------------+---------------------+------+-----+---------+----------------+
      | id          | bigint(11) unsigned | NO   | PRI | NULL    | auto_increment |
      | country     | varchar(300)        | NO   |     | NULL    |                |
      | province    | varchar(300)        | NO   |     | NULL    |                |
      | min_zipcode | int(5) unsigned     | NO   |     | NULL    |                |
      | max_zipcode | int(5) unsigned     | NO   |     | NULL    |                |
      +-------------+---------------------+------+-----+---------+----------------+
      
      mysql> DESC `regions`;
      +-------------+------------------+------+-----+---------+----------------+
      | Field       | Type             | Null | Key | Default | Extra          |
      +-------------+------------------+------+-----+---------+----------------+
      | id          | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
      | provinceid  | int(11) unsigned | NO   |     | NULL    |                |
      | region      | varchar(300)     | NO   |     | NULL    |                |
      | min_zipcode | int(5) unsigned  | NO   |     | NULL    |                |
      | max_zipcode | int(5) unsigned  | NO   |     | NULL    |                |
      +-------------+------------------+------+-----+---------+----------------+
      
      mysql> DESC `issues`;
      +------------+---------------------+------+-----+---------+----------------+
      | Field      | Type                | Null | Key | Default | Extra          |
      +------------+---------------------+------+-----+---------+----------------+
      | id         | bigint(11) unsigned | NO   | PRI | NULL    | auto_increment |
      | categoryid | int(11) unsigned    | NO   |     | NULL    |                |
      | country    | varchar(150)        | NO   |     | NULL    |                |
      | zipcode    | int(5)              | NO   |     | NULL    |                |
      +------------+---------------------+------+-----+---------+----------------+
      
      mysql> DESC `experts`;
      +---------+------------------+------+-----+---------+----------------+
      | Field   | Type             | Null | Key | Default | Extra          |
      +---------+------------------+------+-----+---------+----------------+
      | id      | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
      | country | varchar(150)     | NO   |     | none    |                |
      +---------+------------------+------+-----+---------+----------------+
      
      mysql> DESC `experts_categories`;
      +------------+------------------+------+-----+---------+-------+
      | Field      | Type             | Null | Key | Default | Extra |
      +------------+------------------+------+-----+---------+-------+
      | expertid   | int(11) unsigned | NO   | PRI | NULL    |       |
      | categoryid | int(11) unsigned | NO   | PRI | NULL    |       |
      +------------+------------------+------+-----+---------+-------+
      
      mysql> DESC `experts_provinces`;
      +------------+------------------+------+-----+---------+-------+
      | Field      | Type             | Null | Key | Default | Extra |
      +------------+------------------+------+-----+---------+-------+
      | expertid   | int(11) unsigned | NO   | PRI | NULL    |       |
      | provinceid | int(11) unsigned | NO   | PRI | NULL    |       |
      +------------+------------------+------+-----+---------+-------+
      
      mysql> DESC `experts_regions`;
      +----------+---------+------+-----+---------+-------+
      | Field    | Type    | Null | Key | Default | Extra |
      +----------+---------+------+-----+---------+-------+
      | expertid | int(11) | NO   | PRI | NULL    |       |
      | regionid | int(11) | NO   | PRI | NULL    |       |
      +----------+---------+------+-----+---------+-------+
      

      4。视觉记录

      mysql> SELECT * FROM `categories`;
      +----+----------+
      | id | name     |
      +----+----------+
      |  1 | Software |
      |  2 | Hardware |
      +----+----------+
      
      mysql> SELECT * FROM `provinces`;
      +----+---------+----------------+-------------+-------------+
      | id | country | province       | min_zipcode | max_zipcode |
      +----+---------+----------------+-------------+-------------+
      |  1 | Germany | Province One   |        1000 |        1299 |
      |  2 | Germany | Province Two   |        1300 |        1499 |
      |  3 | Germany | Province Three |        1500 |        1999 |
      |  4 | Germany | Province Four  |        2000 |        2899 |
      |  5 | France  | Province One   |        1000 |        1799 |
      |  6 | France  | Province Two   |        1800 |        2199 |
      |  7 | France  | Province Three |        2200 |        2399 |
      +----+---------+----------------+-------------+-------------+
      
      mysql> SELECT * FROM `regions`;
      +----+------------+--------------+-------------+-------------+
      | id | provinceid | region       | min_zipcode | max_zipcode |
      +----+------------+--------------+-------------+-------------+
      |  1 |          1 | Region One   |        1000 |        1099 |
      |  2 |          1 | Region Two   |        1100 |        1159 |
      |  3 |          1 | Region Three |        1160 |        1299 |
      |  4 |          2 | Region One   |        1300 |        1400 |
      |  5 |          2 | Region Two   |        1401 |        1499 |
      |  6 |          3 | Region One   |        1500 |        1699 |
      |  7 |          3 | Region Two   |        1700 |        1999 |
      |  8 |          4 | Region One   |        2000 |        2299 |
      |  9 |          4 | Region Two   |        2300 |        2599 |
      | 10 |          4 | Region Three |        2600 |        2699 |
      | 11 |          4 | Region Four  |        2700 |        2899 |
      | 12 |          5 | Region One   |        1000 |        1699 |
      | 13 |          5 | Region Two   |        1700 |        1799 |
      | 14 |          6 | Region One   |        1800 |        2000 |
      | 15 |          6 | Region Two   |        2001 |        2199 |
      | 16 |          7 | Region One   |        2200 |        2299 |
      | 17 |          7 | Region Two   |        2300 |        2399 |
      +----+------------+--------------+-------------+-------------+
      
      mysql> SELECT * FROM `issues`;
      +----+------------+---------+---------+
      | id | categoryid | country | zipcode |
      +----+------------+---------+---------+
      |  1 |          2 | Germany |    2100 |
      |  2 |          1 | France  |    1900 |
      |  3 |          1 | Germany |    1500 |
      |  4 |          2 | Germany |    2800 |
      |  5 |          2 | France  |    1850 |
      +----+------------+---------+---------+
      
      mysql> SELECT * FROM `experts`;
      +----+---------+
      | id | country |
      +----+---------+
      |  1 | Germany |
      |  2 | France  |
      |  3 | Germany |
      +----+---------+
      
      mysql> SELECT * FROM `experts_categories`;
      +----------+------------+
      | expertid | categoryid |
      +----------+------------+
      |        1 |          1 |
      |        1 |          2 |
      |        2 |          1 |
      |        3 |          1 |
      +----------+------------+
      
      mysql> SELECT * FROM `experts_provinces`;
      +----------+------------+
      | expertid | provinceid |
      +----------+------------+
      |        1 |          4 |
      |        2 |          6 |
      |        2 |          7 |
      +----------+------------+
      
      mysql> SELECT * FROM `experts_regions`;
      +----------+----------+
      | expertid | regionid |
      +----------+----------+
      |        1 |        8 |
      |        1 |       10 |
      +----------+----------+
      

      III。溶液

      我设法提出了一半的解决方案。

      1。我的半解决方案

      a)查询:

      SELECT 
              `i`.`id` `issue_id`, 
              `e`.`id` `expert_id`
      FROM `issues` `i` 
      INNER JOIN `experts` `e` 
              ON `i`.`country` = `e`.`country` 
      INNER JOIN `experts_categories` `ec` 
              ON `e`.`id` = `ec`.`expertid` 
              AND `i`.`categoryid` = `ec`.`categoryid`
      ORDER BY `e`.`id`, `ec`.`categoryid` ASC
      

      b)结果:

      +----------+-----------+
      | issue_id | expert_id |
      +----------+-----------+
      |        3 |         1 |
      |        1 |         1 |
      |        4 |         1 |
      |        2 |         2 |
      |        3 |         3 |
      +----------+-----------+
      

      c)准确的结果是:

      +----------+-----------+
      | issue_id | expert_id |
      +----------+-----------+
      |        1 |         1 |
      |        2 |         2 |
      |        3 |         3 |
      +----------+-----------+
      

      解释,为什么上述视觉结果是准确的。

      首先,让我们得到一个“完全加入”,这样我们就可以进行比较:
      d)查询:

      SELECT 
              `i`.`id` `issue_id`, `e`.`id` `expert_id`, `i`.`categoryid` `issue_category_id`, `ec`.`categoryid` `expert_category_id`, 
              `i`.`country` `issue_country`, `e`.`country` `expert_country`,
              `i`.`zipcode` `issue_zipcode`,
              `p`.`id` `province_id`, `p`.`min_zipcode` `province_min_zipcode`, `p`.`max_zipcode` `province_max_zipcode`,
              `r`.`id` `region_id`, `r`.`min_zipcode` `region_min_zipcode`, `r`.`max_zipcode` `region_max_zipcode`
      FROM `issues` `i`
      INNER JOIN `experts` `e` 
              ON `i`.`country` = `e`.`country`
      INNER JOIN `experts_categories` `ec` 
              ON `ec`.`expertid` = `e`.`id`
              AND `i`.`categoryid` = `ec`.`categoryid`
      LEFT JOIN `experts_provinces` `ep`
              ON `e`.`id` = `ep`.`expertid`
      LEFT JOIN `provinces` `p`
              ON `ep`.`provinceid` = `p`.`id`
      LEFT JOIN `experts_regions` `er`
              ON `e`.`id` = `er`.`expertid`
      LEFT JOIN `regions` `r`
              ON `er`.`regionid` = `r`.`id`
              AND `p`.`id` = `r`.`provinceid`
      ORDER BY `e`.`id`,`ec`.`categoryid` ASC
      

      e)结果:

      +----------+-----------+-------------------+--------------------+---------------+----------------+---------------+-------------+----------------------+----------------------+-----------+--------------------+--------------------+
      | issue_id | expert_id | issue_category_id | expert_category_id | issue_country | expert_country | issue_zipcode | province_id | province_min_zipcode | province_max_zipcode | region_id | region_min_zipcode | region_max_zipcode |
      +----------+-----------+-------------------+--------------------+---------------+----------------+---------------+-------------+----------------------+----------------------+-----------+--------------------+--------------------+
      |        3 |         1 |                 1 |                  1 | Germany       | Germany        |          1500 |           4 |                 2000 |                 2899 |        10 |               2600 |               2699 |
      |        3 |         1 |                 1 |                  1 | Germany       | Germany        |          1500 |           4 |                 2000 |                 2899 |         8 |               2000 |               2299 |
      |        1 |         1 |                 2 |                  2 | Germany       | Germany        |          2100 |           4 |                 2000 |                 2899 |        10 |               2600 |               2699 |
      |        1 |         1 |                 2 |                  2 | Germany       | Germany        |          2100 |           4 |                 2000 |                 2899 |         8 |               2000 |               2299 |
      |        4 |         1 |                 2 |                  2 | Germany       | Germany        |          2800 |           4 |                 2000 |                 2899 |        10 |               2600 |               2699 |
      |        4 |         1 |                 2 |                  2 | Germany       | Germany        |          2800 |           4 |                 2000 |                 2899 |         8 |               2000 |               2299 |
      |        2 |         2 |                 1 |                  1 | France        | France         |          1900 |           7 |                 2200 |                 2399 |      NULL |               NULL |               NULL |
      |        2 |         2 |                 1 |                  1 | France        | France         |          1900 |           6 |                 1800 |                 2199 |      NULL |               NULL |               NULL |
      |        3 |         3 |                 1 |                  1 | Germany       | Germany        |          1500 |        NULL |                 NULL |                 NULL |      NULL |               NULL |               NULL |
      +----------+-----------+-------------------+--------------------+---------------+----------------+---------------+-------------+----------------------+----------------------+-----------+--------------------+--------------------+
      

      因此,将(b)查询结果与(c),手动修正结果进行比较,我们可以注意到......

      1. issue_id号码3可以分配给expert_id号码1,因为issue_id号码1来自国家/地区Germany,就像专家一样,在category_id号码2上分配,就像专家一样,有邮政编码{{1已分配1500号码expert_id仅从1号码issuesprovince_id号码4获取regions_id8内的10。因此,province邮政编码的范围从regions2000,从22992600,我们的2699邮政编码不属于此类。< / LI>
      2. issue号码issue_id可以分配到1号码expert_id,因为1号码issue_id来自国家/地区1就像专家一样,在Germany号码category_id上分配,就像专家一样,有一个邮政编码2,位于2100号码的边界之间省内的province_id4号码region_id已分配给8号码expert_id
      3. 1号码issue_id可以分配给4号码expert_id,因为1号码issue_id来自国家/地区4,就像专家一样,在Germany号码category_id上分配,但是有一个邮政编码4,这是在2800号码province_id的边界内,但在4号码region_id8的边界内 ,已分配给10号码expert_id
      4. 1号码issue_id可以分配到2号码expert_id,因为2号码issue_id来自国家/地区2就像专家一样,在France号码category_id上分配,就像专家一样,有一个邮政编码1,它位于1900号码的边界内province_id,由此专家指定。
      5. 6号码issue_id可以分配到3号码expert_id,因为3号码issue_id来自国家/地区3就像专家一样,在Germany号码category_id上分配,就像专家一样。此外,该专家没有任何行政区划限制。也就是说,此专家可以从所有1
      6. 中获取issues

        因此,我们列出了可以分配给Germany的所有issues

        2。缺少一半解决方案

        如您所见,我的半解决方案没有考虑行政区划限制 我不能使用程序或视图来实现这一点,但是,如果有帮助,我可以在多个查询中将其拆分。

        数据库是MySQL(5.0.1 - MySQL社区服务器(GPL)),编程语言是PHP(5.1)。

2 个答案:

答案 0 :(得分:3)

我只是修改@krubo的答案。

如果您想要子查询,查询将是:

SELECT 
    tis.id AS issue_id, 
    tex.id AS expert_id, 
    tis.categoryid AS issue_category_id,
    tex.categoryid AS expert_category_id,
    tis.country AS issue_country,
    tex.country AS expert_country,
    tis.zipcode AS issue_zipcode,
    tis.provinceid AS province_id,
    tis.province_minzipcode AS province_minzipcode,
    tis.province_maxzipcode AS province_maxzipcode,
    tis.regionid AS region_id,
    tis.region_minzipcode AS region_minzipcode,
    tis.region_maxzipcode AS region_maxzipcode
FROM 
(
    SELECT 
        i.id, categoryid, i.country, zipcode, 
        provinces.id AS provinceid, provinces.min_zipcode AS province_minzipcode,
        provinces.max_zipcode AS province_maxzipcode, regions.id AS regionid, 
        regions.min_zipcode AS region_minzipcode, 
        regions.max_zipcode AS region_maxzipcode
    FROM 
        issues AS i 
    LEFT JOIN provinces ON i.country=provinces.country
      AND i.zipcode BETWEEN provinces.min_zipcode AND provinces.max_zipcode
    LEFT JOIN regions on provinces.id=regions.provinceid
      AND i.zipcode BETWEEN regions.min_zipcode AND regions.max_zipcode
) AS tis 
JOIN 
( 
    SELECT 
       e.id, country, categoryid, provinceid, regionid
    FROM 
       experts e
    JOIN experts_categories ON e.id=experts_categories.expertid
    LEFT JOIN experts_provinces ON e.id=experts_provinces.expertid
    LEFT JOIN experts_regions ON e.id=experts_regions.expertid
) AS tex  
WHERE 
    tis.country=tex.country
    AND tis.categoryid=tex.categoryid
    AND (tis.provinceid IS NULL
        OR tex.provinceid IS NULL
        OR tis.provinceid=tex.provinceid)
    AND (tis.regionid IS NULL
        OR tex.regionid IS NULL
        OR tis.regionid=tex.regionid);

结果是:

+----------+-----------+-------------------+--------------------+---------------+----------------+---------------+-------------+----------------------+----------------------+-----------+--------------------+--------------------+
| issue_id | expert_id | issue_category_id | expert_category_id | issue_country | expert_country | issue_zipcode | province_id | province_min_zipcode | province_max_zipcode | region_id | region_min_zipcode | region_max_zipcode |
+----------+-----------+-------------------+--------------------+---------------+----------------+---------------+-------------+----------------------+----------------------+-----------+--------------------+--------------------+
|        1 |         1 |                 2 |                  2 | Germany       | Germany        |          2100 |           4 |                 2000 |                 2899 |         8 |               2000 |               2299 |
|        2 |         2 |                 1 |                  1 | France        | France         |          1900 |           6 |                 2000 |                 2199 |        14 |               1800 |               2000 |
|        3 |         3 |                 1 |                  1 | Germany       | Germany        |          1500 |           3 |                 2000 |                 1999 |         6 |               1500 |               1699 |

答案 1 :(得分:2)

如果您不使用至少一个视图来组织它,那么您的SQL将非常复杂。尝试使用此视图将每个问题与省和地区相匹配:

create view viewissues as
   select issues.id, categoryid, issues.country, zipcode,
      provinces.id as provinceid, regions.id as regionid
   from issues
   left join provinces on issues.country=provinces.country
      and issues.zipcode between provinces.min_zipcode and provinces.max_zipcode
   left join regions on provinces.id=regions.provinceid
      and issues.zipcode between regions.min_zipcode and regions.max_zipcode;

此视图根据类别,省份(如果有)和区域(如果有)列出专家:

create view viewexperts as
   select experts.id, country, categoryid, provinceid, regionid
   from experts
   join experts_categories on experts.id=experts_categories.expertid
   left join experts_provinces on experts.id=experts_provinces.expertid
   left join experts_regions on experts.id=experts_regions.expertid;

现在,通过根据这些视图进行选择,您的最终查询可以更易于管理:

select distinct viewissues.id, viewexperts.id
from viewissues join viewexperts
where viewissues.country=viewexperts.country
and viewissues.categoryid=viewexperts.categoryid
and (viewissues.provinceid is null
  or viewexperts.provinceid is null
  or viewissues.provinceid=viewexperts.provinceid)
and (viewissues.regionid is null
  or viewexperts.regionid is null
  or viewissues.regionid=viewexperts.regionid);