Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/232.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 选择与MySql中一对多关系右侧匹配的行_Php_Mysql_Sql_Join_Pdo - Fatal编程技术网

Php 选择与MySql中一对多关系右侧匹配的行

Php 选择与MySql中一对多关系右侧匹配的行,php,mysql,sql,join,pdo,Php,Mysql,Sql,Join,Pdo,我有四张桌子。一个用于公司,一个用于产品,一个用于公司地址,一个用于公司董事 products、director和address表与company表具有一对多关系 因此,一家公司可以有许多产品、许多地址和许多董事 CREATE TABLE IF NOT EXISTS `companies` ( `company_id` int(11) NOT NULL AUTO_INCREMENT, `company_name` varchar(50) NOT NULL, PRIMARY KEY (

我有四张桌子。一个用于公司,一个用于产品,一个用于公司地址,一个用于公司董事

products、director和address表与company表具有一对多关系

因此,一家公司可以有许多产品、许多地址和许多董事

CREATE TABLE IF NOT EXISTS `companies` (
  `company_id` int(11) NOT NULL AUTO_INCREMENT,
  `company_name` varchar(50) NOT NULL,
  PRIMARY KEY (`company_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ;

CREATE TABLE IF NOT EXISTS `products` (
  `product_id` int(11) NOT NULL AUTO_INCREMENT,
  `company_id` int(11) NOT NULL,
  `product` varchar(50) NOT NULL,
  PRIMARY KEY (`product_id`),
  KEY `company_id` (`company_id`),
  KEY `product` (`product`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

CREATE TABLE IF NOT EXISTS `directors` (
  `director_id` int(11) NOT NULL AUTO_INCREMENT,
  `company_id` int(11) NOT NULL,
  `surname` varchar(100) NOT NULL,
  `dob` date NOT NULL,
  PRIMARY KEY (`director_id`),
  KEY `company_id` (`company_id`),
  KEY `surname` (`surname`),
  KEY `dob` (`dob`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=6 ;

CREATE TABLE IF NOT EXISTS `addresses` (
  `address_id` int(11) NOT NULL AUTO_INCREMENT,
  `company_id` int(1) NOT NULL,
  `postcode` varchar(10) NOT NULL,
  PRIMARY KEY (`address_id`),
  KEY `company_id` (`company_id`),
  KEY `postcode` (`postcode`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;

INSERT INTO `companies` (`company_id`, `company_name`) VALUES
(1, 'Honda'),
(2, 'Toyota');

INSERT INTO `products` (`product_id`, `company_id`, `product`) VALUES
(1, 1, 'Civic'),
(2, 1, 'Accord'),
(3, 2, 'Corolla'),
(4, 2, 'Prius'),
(5, 1, 'CRV');

INSERT INTO `directors` (`director_id`, `company_id`, `surname`, `dob`)     VALUES
(1, 1, 'Jones', '1990-09-09'),
(2, 1, 'Smith', '1980-08-08'),
(3, 2, 'Lucas', '1970-07-07'),
(4, 1, 'Kelly', '1960-06-06'),
(5, 2, 'Monty', '1950-05-05');

INSERT INTO `addresses` (`address_id`, `company_id`, `postcode`) VALUES
(6, 1, '12345'),
(7, 2, '23456'),
(8, 1, '34567'),
(9, 2, '45678'),
(10, 1, '56789');
我正在尝试编写一个高效的查询(使用MySql/PDO)来为匹配主管(姓氏和dob)和地址(邮政编码)的公司查找产品

我只想每行列出一个匹配的产品,而不是单独列出每个导演或邮政编码

到目前为止,我有下面的查询,这似乎是可行的,但它是丑陋的,我怀疑这是一个荒谬的方式进行这方面的速度和效率

SELECT product
FROM products p
LEFT JOIN companies c USING(company_id)
WHERE :lname IN ( 
    SELECT surname 
    FROM directors d 
    WHERE c.company_id = d.company_id )
AND :dob IN ( 
    SELECT dob 
    FROM directors d 
    WHERE c.company_id = d.company_id )
AND :postcode IN ( 
    SELECT postcode 
    FROM addresses a 
    WHERE c.company_id = a.company_id )

提前感谢您的帮助。

至少,可以通过使用
exists
操作符而不是
中的
重写
directors
上的两个子查询来统一它们。为了更好地度量,我用这个操作符重写了整个查询,尽管严格来说这不是必需的:

SELECT    product
FROM      products p
LEFT JOIN companies c USING(company_id)
WHERE     EXISTS (SELECT * 
                  FROM directors d 
                  WHERE c.company_id = d.company_id AND 
                        (:lname  = d.lanme OR :dob = d.dob)) AND
           EXISTS (SELECT * 
                   FROM addresses a 
                   WHERE c.company_id = a.company_id AND :postcode = a.postcode)

不确定为什么需要子查询

SELECT p.product FROM products p
INNER JOIN companies c USING(company_id)
INNER JOIN directors d ON d.company_id = c.company_id AND d.surname = 'Jones' AND d.dob = '1990-09-09'
INNER JOIN addresses a ON a.company_id = c.company_id AND a.postcode = '12345'


如果您对这两个查询进行解释,您会发现它们在内部是相同的。

您希望“更好”的工作代码最好发布在上面,我会重新思考您的底层数据结构。。。我不知道如何使用
姓氏
出生地
、以及
邮政编码
。如果您有
姓氏
dob
,则通过董事表您有
公司id
。。。那么,您为什么需要
邮政编码中
地址表中的
公司id
?这没有道理。谢谢你@upful。并非所有公司都必须有地址记录,也并非所有公司都必须有董事。它们是两个独立的东西,必须用墨水写在公司表上,因此我能看到的唯一方法是通过公司ID。在这种情况下,您可能会使用
操作符,而不是
。。。所以
其中(姓氏=:姓氏和出生日期=:出生日期)或邮政编码=:杀虫剂
。。。此外,我认为确定哪家公司的产品与您的搜索结果相匹配是很重要的,而不仅仅是返回产品列表。谢谢您的回答。问题是,它为同一产品返回多行,每个债务人或邮政编码返回一行,然后您可以使用DISTINCT。e、 g.
选择不同的p.product…
谢谢。非常有用。这就是我最终使用的解决方案
SELECT p.product FROM products p
INNER JOIN companies c USING(company_id)
INNER JOIN directors d USING(company_id) 
INNER JOIN addresses a USING(company_id)
WHERE d.surname = 'Jones'
AND d.dob = '1990-09-09'
AND a.postcode = '12345'