MySQL 与 LEFT JOINS 相关的子查询
MySQL Subquery related to LEFT JOINS
我接到了从数据库中提取客户信息的任务,但我卡在了最后一部分!我希望我的解释足以描述我的问题和尝试。
目标:Return 每个客户排成一排,所有 phone 号码
问题:每个客户可能有很多 phone 个号码
尝试次数:
SUBQUERY:出现 "Subquery returning more than 1 row" 错误。这对我来说很有意义,但我不能为每个客户插入 WHERE 语句
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE,
(SELECT telephone.Number
FROM customer
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone ON customertelephone.TelephoneID = telephone.TelephoneID
WHERE telephone.Type = "Main") as MainPhone
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LIMIT 100
LEFT JOIN:查询 return 一个 row/customer/number,但我需要每个数字在一行中。
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, telephone.Number
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone ON customertelephone.TelephoneID = telephone.TelephoneID
LIMIT 100
GROUP BY:查询正确 return 每个客户一行,但只有 return 第一个数字。
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, telephone.Number
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone ON customertelephone.TelephoneID = telephone.TelephoneID
GROUP BY customer.CustomerID
LIMIT 100
我如何 return 每个客户在一行中仅在一行中显示他们的每个 phone 号码?
编辑:
我刚刚得到了一些很棒的帮助:group_concat 创造奇迹!现在我正在尝试正确格式化查询 return。
目标:将 GROUP_CONCAT 编辑的值 return 分离到新字段中
当前SQL代码:
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, GROUP_CONCAT(telephone.Number) as TelephoneNumbers, GROUP_CONCAT(telephone.Type) as Types
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone ON customertelephone.TelephoneID = telephone.TelephoneID
GROUP BY customer.CustomerID
GROUP_CONACT的当前结果:
TelephoneNumbers Type
321-000-0000,321-000-0000 Main, Fax
321-001-0000 Mobile
我想要达到的目标:
Main Fax Mobile
321-000-0000 321-000-0000 NULL
NULL NULL 321-001-0000
尝试:
GROUP_CONCAT 中的 WHERE 语句引发错误
GROUP_CONCAT(telephone.Number WHERE GROUP_CONCAT(telephone.Type) = "MAIN") as Main
有没有可能做到这一点?
编辑:
最终代码(感谢user4829935!):
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, GROUP_CONCAT(tmain.Number) as Main, GROUP_CONCAT(tmobile.Number) as Mobile, GROUP_CONCAT(tfax.Number) as Fax
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone as tmain ON customertelephone.TelephoneID = tmain.TelephoneID AND tmain.type = 'Main'
LEFT JOIN telephone as tmobile ON customertelephone.TelephoneID = tmobile.TelephoneID AND tmobile.type = 'Mobile'
LEFT JOIN telephone as tfax ON customertelephone.TelephoneID = tfax.TelephoneID AND tfax.type = 'Fax'
GROUP BY customer.CustomerID
试试这个:
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, GROUP_CONCAT(telephone.Number)
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone ON customertelephone.TelephoneID = telephone.TelephoneID
GROUP BY customer.CustomerID
您将得到 phone 个以逗号分隔的数字。
编辑:
获取不同的数字作为不同的字段,如:
name street city state zip ... main_phone fax
John Doe 123 Main St Springfield CA 99999 123-555-5555 123-555-5556
您需要提前知道 phone 号码的可能类型,并将它们编码到查询中。那是你想要的吗?
那会是这样的:
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, GROUP_CONCAT(tm.Number) as mainTelephone, GROUP_CONCAT(tf.Number) as fax
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone as tm ON customertelephone.TelephoneID = tm.TelephoneID AND tm.type = 'mainTelephone'
LEFT JOIN telephone as tf ON customertelephone.TelephoneID = tf.TelephoneID AND tf.type = 'fax'
GROUP BY customer.CustomerID
(我的脑子里打不出来,因为我没有你的数据来验证我的查询。可能有错别字)
MySQL提供聚合函数GROUP_CONCAT
.
参考:https://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html#function_group-concat
(我不打算在这里重复整个文档。)
一些重要注意事项:GROUP_CONCAT
编辑的字符串 return 的长度受 max_group_concat_len
变量和 max_allowed_packet
变量设置的限制。
如果字符串较长,它会自动截断至允许的最大长度。您可能需要检查 returned 字符串的长度并将其与最大允许长度进行比较以验证它没有被截断。
DISTINCT
关键字对于消除重复项很有用。
ORDER BY
可用于使 returned 字符串更具确定性。
默认分隔符是逗号,但也可以指定。
跟进
要通过 type
获得不同的 phone 数字列表,您可以在 CASE
表达式或 IF
函数中使用条件测试,以有条件地 return 一个值或一个 NULL。只需将该表达式包装在聚合函数中,如 GROUP_CONCAT
,例如
SELECT GROUP_CONCAT( IF(t.type='main' ,t.number,NULL) ) AS main_numbers
, GROUP_CONCAT( IF(t.type='mobile',t.number,NULL) ) AS mobile_numbers
, ...
LEFT JOIN telephone t ON ...
如果每种类型只需要一个数字,则可以改用 MAX
聚合函数,例如
SELECT MAX( IF(t.type='main' ,t.number,NULL) ) AS a_main_number
, MAX( IF(t.type='mobile',t.number,NULL) ) AS a_mobile_number
, ...
LEFT JOIN telephone t ON ...
作为另一种选择(通常性能不佳),您可以使用 SELECT 列表中的相关子查询获得等效结果。
SELECT c.customerID
, ( SELECT t.number
FROM customertelephone ct
JOIN telephone t
ON t.telephoneID = ct.telephoneID
AND t.type = 'main' -- main
WHERE ct.customerID = c.customerID -- match column from outer query
ORDER BY t.telephoneID
LIMIT 0,1 -- first row
) AS main_number_1
, ( SELECT t.number
FROM customertelephone ct
JOIN telephone t
ON t.telephoneID = ct.telephoneID
AND t.type = 'main' -- main
WHERE ct.customerID = c.customerID -- match column from outer query
ORDER BY t.telephoneID
LIMIT 1,1 -- second row
) AS main_number_2
, ( SELECT t.number
FROM customertelephone ct
JOIN telephone t
ON t.telephoneID = ct.telephoneID
AND t.type = 'mobile' -- mobile
WHERE ct.customerID = c.customerID -- match column from outer query
ORDER BY t.telephoneID
LIMIT 0,1
) AS mobile_number_1
FROM customer c
我接到了从数据库中提取客户信息的任务,但我卡在了最后一部分!我希望我的解释足以描述我的问题和尝试。
目标:Return 每个客户排成一排,所有 phone 号码
问题:每个客户可能有很多 phone 个号码
尝试次数:
SUBQUERY:出现 "Subquery returning more than 1 row" 错误。这对我来说很有意义,但我不能为每个客户插入 WHERE 语句
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE,
(SELECT telephone.Number
FROM customer
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone ON customertelephone.TelephoneID = telephone.TelephoneID
WHERE telephone.Type = "Main") as MainPhone
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LIMIT 100
LEFT JOIN:查询 return 一个 row/customer/number,但我需要每个数字在一行中。
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, telephone.Number
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone ON customertelephone.TelephoneID = telephone.TelephoneID
LIMIT 100
GROUP BY:查询正确 return 每个客户一行,但只有 return 第一个数字。
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, telephone.Number
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone ON customertelephone.TelephoneID = telephone.TelephoneID
GROUP BY customer.CustomerID
LIMIT 100
我如何 return 每个客户在一行中仅在一行中显示他们的每个 phone 号码?
编辑:
我刚刚得到了一些很棒的帮助:group_concat 创造奇迹!现在我正在尝试正确格式化查询 return。
目标:将 GROUP_CONCAT 编辑的值 return 分离到新字段中
当前SQL代码:
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, GROUP_CONCAT(telephone.Number) as TelephoneNumbers, GROUP_CONCAT(telephone.Type) as Types
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone ON customertelephone.TelephoneID = telephone.TelephoneID
GROUP BY customer.CustomerID
GROUP_CONACT的当前结果:
TelephoneNumbers Type
321-000-0000,321-000-0000 Main, Fax
321-001-0000 Mobile
我想要达到的目标:
Main Fax Mobile
321-000-0000 321-000-0000 NULL
NULL NULL 321-001-0000
尝试: GROUP_CONCAT 中的 WHERE 语句引发错误
GROUP_CONCAT(telephone.Number WHERE GROUP_CONCAT(telephone.Type) = "MAIN") as Main
有没有可能做到这一点?
编辑:
最终代码(感谢user4829935!):
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, GROUP_CONCAT(tmain.Number) as Main, GROUP_CONCAT(tmobile.Number) as Mobile, GROUP_CONCAT(tfax.Number) as Fax
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone as tmain ON customertelephone.TelephoneID = tmain.TelephoneID AND tmain.type = 'Main'
LEFT JOIN telephone as tmobile ON customertelephone.TelephoneID = tmobile.TelephoneID AND tmobile.type = 'Mobile'
LEFT JOIN telephone as tfax ON customertelephone.TelephoneID = tfax.TelephoneID AND tfax.type = 'Fax'
GROUP BY customer.CustomerID
试试这个:
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, GROUP_CONCAT(telephone.Number)
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone ON customertelephone.TelephoneID = telephone.TelephoneID
GROUP BY customer.CustomerID
您将得到 phone 个以逗号分隔的数字。
编辑:
获取不同的数字作为不同的字段,如:
name street city state zip ... main_phone fax
John Doe 123 Main St Springfield CA 99999 123-555-5555 123-555-5556
您需要提前知道 phone 号码的可能类型,并将它们编码到查询中。那是你想要的吗?
那会是这样的:
SELECT customer.Name, address.Street, address.City, address.State, address.Zip, customer.Contact, email.Address, customer.CTYPE, GROUP_CONCAT(tm.Number) as mainTelephone, GROUP_CONCAT(tf.Number) as fax
FROM `customer`
LEFT JOIN customeraddress ON customer.CustomerID = customeraddress.CustomerID
LEFT JOIN address ON customeraddress.AddressID = address.AddressID
LEFT JOIN customeremail ON customer.CustomerID = customeremail.CustomerID
LEFT JOIN email ON customeremail.EmailID = email.EMailID
LEFT JOIN customertelephone ON customer.CustomerID = customertelephone.CustomerID
LEFT JOIN telephone as tm ON customertelephone.TelephoneID = tm.TelephoneID AND tm.type = 'mainTelephone'
LEFT JOIN telephone as tf ON customertelephone.TelephoneID = tf.TelephoneID AND tf.type = 'fax'
GROUP BY customer.CustomerID
(我的脑子里打不出来,因为我没有你的数据来验证我的查询。可能有错别字)
MySQL提供聚合函数GROUP_CONCAT
.
参考:https://dev.mysql.com/doc/refman/5.5/en/group-by-functions.html#function_group-concat
(我不打算在这里重复整个文档。)
一些重要注意事项:GROUP_CONCAT
编辑的字符串 return 的长度受 max_group_concat_len
变量和 max_allowed_packet
变量设置的限制。
如果字符串较长,它会自动截断至允许的最大长度。您可能需要检查 returned 字符串的长度并将其与最大允许长度进行比较以验证它没有被截断。
DISTINCT
关键字对于消除重复项很有用。
ORDER BY
可用于使 returned 字符串更具确定性。
默认分隔符是逗号,但也可以指定。
跟进
要通过 type
获得不同的 phone 数字列表,您可以在 CASE
表达式或 IF
函数中使用条件测试,以有条件地 return 一个值或一个 NULL。只需将该表达式包装在聚合函数中,如 GROUP_CONCAT
,例如
SELECT GROUP_CONCAT( IF(t.type='main' ,t.number,NULL) ) AS main_numbers
, GROUP_CONCAT( IF(t.type='mobile',t.number,NULL) ) AS mobile_numbers
, ...
LEFT JOIN telephone t ON ...
如果每种类型只需要一个数字,则可以改用 MAX
聚合函数,例如
SELECT MAX( IF(t.type='main' ,t.number,NULL) ) AS a_main_number
, MAX( IF(t.type='mobile',t.number,NULL) ) AS a_mobile_number
, ...
LEFT JOIN telephone t ON ...
作为另一种选择(通常性能不佳),您可以使用 SELECT 列表中的相关子查询获得等效结果。
SELECT c.customerID
, ( SELECT t.number
FROM customertelephone ct
JOIN telephone t
ON t.telephoneID = ct.telephoneID
AND t.type = 'main' -- main
WHERE ct.customerID = c.customerID -- match column from outer query
ORDER BY t.telephoneID
LIMIT 0,1 -- first row
) AS main_number_1
, ( SELECT t.number
FROM customertelephone ct
JOIN telephone t
ON t.telephoneID = ct.telephoneID
AND t.type = 'main' -- main
WHERE ct.customerID = c.customerID -- match column from outer query
ORDER BY t.telephoneID
LIMIT 1,1 -- second row
) AS main_number_2
, ( SELECT t.number
FROM customertelephone ct
JOIN telephone t
ON t.telephoneID = ct.telephoneID
AND t.type = 'mobile' -- mobile
WHERE ct.customerID = c.customerID -- match column from outer query
ORDER BY t.telephoneID
LIMIT 0,1
) AS mobile_number_1
FROM customer c