简体   繁体   English

MySQL 多表连接

[英]MySQL multiple table joins

I. Intro一、介绍

I am building a support system, where a user from a certain country raises an issue on a certain category, and experts from that country, administrative division, and category get assigned the issue.我正在建立一个支持系统,来自某个国家/地区的用户提出某个类别的问题,来自该国家、行政部门和类别的专家被分配该问题。

Ex User from country Germany with zip code 1000 rises an issue on category Software .来自Germany的前用户 zip 代码1000Software类别上出现问题。 Experts from country Germany , and/or province with zip code boundaries MIN_PROVINCE_ZIPCODE <= 1000 >= MAX_PROVINCE_ZIPCODE , and/or region with zip code boundaries MIN_REGION_ZIPCODE <= 1000 >= MAX_REGION_ZIPCODE , and category Software get assigned the issue.来自Germany国家和/或 zip 代码边界MIN_PROVINCE_ZIPCODE <= 1000 >= MAX_PROVINCE_ZIPCODE的省份和/或Software代码边界MIN_REGION_ZIPCODE <= 1000 >= MAX_REGION_ZIPCODE <= 1000 和/或区域的专家

Ie: Select all issues where issue country is equal to expert country, and issue category is equal to one of experts' categories, and/or issue zip code is greater or equal to minimum province zip code and smaller or equal to maximum province zip code, and/or issue zip code is greater or equal to region minimum zip code and issue code is smaller or equal to zip codes. Ie: Select all issues where issue country is equal to expert country, and issue category is equal to one of experts' categories, and/or issue zip code is greater or equal to minimum province zip code and smaller or equal to maximum province zip code , 和/或发布 zip 代码大于或等于区域最小值 zip 代码并且发布代码小于或等于 zip 代码。

"and/or" means if experts are assigned to take issues from specific administrative division(s), if they are not, then assign them everything that matches their country and category “和/或”是指是否指派专家处理特定行政部门的问题,如果不是,则指派与他们的国家和类别相匹配的所有内容

II.二、 Database Schemas & Records数据库模式和记录

*Keep in mind!* *记住!*

a) Experts can be part of... a) 专家可以参与...

  1. one, multiple, or no category(ies)一个、多个或无类别
  2. one, multiple, or no province(s)一个、多个或没有省份
  3. one, multiple, or no region(s)一个、多个或无区域

b) If experts are NOT part of... b) 如果专家不是...

  1. a category, then no issues will be assigned to them一个类别,那么不会分配给他们任何问题
  2. a province, then all issues for their country and category will be assigned to them一个省,那么他们国家和类别的所有问题都将分配给他们
  3. a region, then all issues for their province(s) will be assigned to them一个地区,那么他们省份的所有问题都将分配给他们

1. Schemas 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. Records 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. Visual Schemas 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. Visual Records 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.三、 Solution解决方案

I have managed to come up with half of the solution.我已经设法想出了一半的解决方案。

1. My half solution 1.我的一半解决方案

a) Query:一个问题:

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) Result: b) 结果:

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

c) Accurate result would have been: c) 准确的结果应该是:

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

Explanation, as to why the above visual result is the accurate one.解释一下,为什么上面的视觉结果是准确的。

First, let's get a "full join" so we can make the comparisons:首先,让我们获得一个“完全连接”,以便我们进行比较:
d) Query: 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) Result: 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 |
+----------+-----------+-------------------+--------------------+---------------+----------------+---------------+-------------+----------------------+----------------------+-----------+--------------------+--------------------+

So comparing (b) query result with (c), manually fixed result, we can notice...所以比较(b)查询结果和(c),手动修复结果,我们可以注意到......

  1. issue_id number 3 can NOT be assigned to expert_id number 1 , because issue_id number 1 is from country Germany , just like the expert, is assigned on the category_id number 2 , just like the expert, BUT has a zip code 1500 , and expert_id number 1 is assigned to take issues only from province_id number 4 and regions_id number 8 and 10 within that province . issue_id编号3不能分配给expert_id编号1 ,因为issue_id编号1来自国家Germany ,就像专家一样,被分配在category_id编号2上,就像专家一样,有一个expert_id代码1500和专家编号1被分配仅从该province_idprovince ID 号4regions_id810处理issues So the regions zip codes range from 2000 to 2299 and from 2600 to 2699 , where our issue zip code does not belong.所以regions zip 代码范围从20002299和从26002699 ,我们的issue zip 代码不属于这些区域。
  2. issue_id number 1 can be assigned to expert_id number 1 , because issue_id number 1 is from country Germany , just like the expert, is assigned on the category_id number 2 , just like the expert, has a zip code 2100 , which is between the boundaries of the province_id number 4 and region_id number 8 within the province, which is assigned to be covered by expert_id number 1 . issue_id number 1可以分配给expert_id number 1 ,因为issue_id number 1来自国家Germany ,就像专家一样,被分配在category_id编号2上,就像专家一样,有一个 zip 代码2100 ,它在边界之间省内的province_id 4号和region_id 8号,分配给expert_id 1号覆盖。
  3. issue_id number 4 can NOT be assigned to expert_id number 1 , because issue_id number 4 is from country Germany , just like the expert, is assigned on the category_id number 4 , BUT has a zip code 2800 , which is within the boundaries of the province_id number 4 , but it is not within the boundaries of the region_id number 8 and 10 , which is assigned to be covered by expert_id number 1 issue_id number 4不能分配给expert_id number 1 ,因为issue_id number 4来自国家Germany ,就像专家一样,被分配在category_id number 4上,但是有一个 zip 代码2800 ,它在province_id编号的边界内4 ,但不在region_id编号810的边界内,它被分配为由expert_id编号1覆盖
  4. issue_id number 2 can be assigned to expert_id number 2 , because issue_id number 2 is from country France , just like the expert, is assigned on the category_id number 1 , just like the expert, has a zip code 1900 , which is within the boundaries of the province_id number 6 , assigned to be covered by this expert. issue_id number 2可以分配给expert_id number 2 ,因为issue_id number 2来自国家France ,就像专家一样,被分配在category_id编号1上,就像专家一样,有一个 zip 代码1900 ,在边界内province_id编号6 ,分配给该专家。
  5. issue_id number 3 can be assigned to expert_id number 3 , because issue_id number 3 is from country Germany , just like the expert, is assigned on the category_id number 1 , just like the expert. issue_id number 3可以分配给expert_id number 3 ,因为issue_id number 3来自国家Germany ,就像专家一样,被分配在category_id编号1上,就像专家一样。 Furthermore, this expert does not have any administrative division restriction.而且,这位专家没有任何行政区划限制。 That is, this expert can take issues from all Germany也就是说,这位专家可以issues所有Germany的问题

Thus, we have listed all issues that can be assigned to experts .因此,我们列出了所有可以分配给expertsissues

2. Missing half solution 2. 缺半解

As you can see, my half solution does not take into account the administrative division restrictions.如您所见,我的半解决方案没有考虑行政区划限制。
I can not use procedure(s) or views to achieve this, though, I can split it up in multiple queries if that would help.我不能使用过程或视图来实现这一点,但是,如果有帮助的话,我可以将其拆分为多个查询。

Database is MySQL (5.0.1 - MySQL Community Server (GPL)) and programming language is PHP (5.1).数据库为 MySQL (5.0.1 - MySQL 社区服务器 (GPL)),编程语言为 PHP (5.1)。

I just modify the answer from @krubo.我只是修改了@krubo 的答案。

If you want sub-query, the query would be:如果你想要子查询,查询将是:

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);

The result is:结果是:

+----------+-----------+-------------------+--------------------+---------------+----------------+---------------+-------------+----------------------+----------------------+-----------+--------------------+--------------------+
| 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 |

Your SQL will be very complex if you don't use at least one view to organize it.如果您不使用至少一个视图来组织它,您的 SQL 将非常复杂。 Try this view to match each issue with a province and region:尝试使用此视图将每个问题与省和地区匹配:

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;

and this view to list experts according to their categories, provinces if any, and regions if any:此视图根据专家的类别、省份(如果有)和地区(如果有)列出专家:

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;

Now your final query can be more manageable, by selecting based on these views:现在,通过基于这些视图进行选择,您的最终查询可以更易于管理:

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM