Reputation: 51
Hi what I'm trying to do is obtain some customer details from one table and also all of their items in another table through one query. The current issue with my subquery is that it will return more than 1 row and cause an error. Is there a way around this or should I use 2 separate queries?
I'd like to use PDO fetchAll() on the query to return their first and last name and a subarray containing all of the items.
So the results would be accessible by $result['First Name'], $result['First Name'], $result['product'][0], $result['product'][1], $result['product'][3] etc.
Current statement:
SELECT `First Name`, `Last Name`,
(SELECT `items`.`Product Name` from items
inner join customers on `customers`.`Customer No` = `items`.`Customer No`
WHERE `customers`.`Customer No` = '6')
AS product from customers where `Customer No` = '6'
Upvotes: 1
Views: 1504
Reputation: 1509
I don't think it's possible to return an array within one row, but what you can do is use group_concat
to join the values in to a string which you can then explode later on:
SELECT `customers`.`First Name`, `customers`.`Last Name`,
GROUP_CONCAT(`items`.`Product Name` SEPARATOR '$^$') AS `Products`
FROM customers
JOIN items
ON `customers`.`Customer No` = `items`.`Customer No`
WHERE `customers`.`Customer No` = 6
GROUP BY `Customer No`
$products=explode("$^$",$result[0]['products']);
The default separator for group_concat
is ,
which can be quite dangerous when using explode so we use SEPARATOR '$^$'
to add a bunch of random characters that are not likely to turn up instead.
Upvotes: 1
Reputation: 108480
If you want to return just one row, you can add a LIMIT 1. But I don't think that's what you want, though.
If you want to return all items associated with a customer, you can use a LEFT JOIN, like this:
SELECT c.`First Name`
, c.`Last Name`
, i.`Product Name` AS product
FROM customers c
LEFT
JOIN items i
ON i.`Customer No` = c.`Customer No`
WHERE c.`Customer No` = '6'
NOTE: the LEFT JOIN
will return all rows from customers, along with any matching rows from items. If there is a customer that does not have any rows in the items tale, the product
column will be NULL. If you want to exclude customers that don't have any items (if you don't want to get a row back), then remove the LEFT
keyword. The absence of the LEFT
keyword is equivalent to specifying the unnecessary keyword INNER
).
To get a single row back from the customers table, along with just one related item, then your approach using a subquery in the SELECT list can be effective.
But you don't need to do a JOIN operation in that subquery, you can reference values from the outer query (make it a correlated subquery). The key here though is adding a LIMIT 1 to the subquery to ensure that it returns no more than 1 row.
SELECT `First Name`
, `Last Name`
, ( SELECT `items`.`Product Name`
FROM `items`
WHERE `items`.`Customer No` = `customers`.`Customer No`
ORDER BY `items`.`Product Name`
LIMIT 1
) AS product
FROM customers
WHERE `Customer No` = '6'
The ORDER BY isn't necessary, but it makes the resultset deterministic. That is, absent the ORDER BY, MySQL is free to return any one of the rows that satisfy the predicate. And subsequent runs could return a different result. There's nothing wrong with that, but it can be unexpected if you aren't expecting it.
Upvotes: 1
Reputation: 263843
try joining them,
SELECT a.`First Name`,
a.`Last Name`,
b.`Product Name`
FROM customers a
INNER JOIN items b
ON a.`Customer No` = b.`Customer No`
WHERE a.`Customer No` = '6'
This query will return only customers
that has atleast one match on table item
due to the type of join define: INNER JOIN
. However, if you still want records of customer to show/retrieve whether it has a matching value or not on table Items
, change INNER JOIN
into LEFT JOIN
(an OUTER join)
To learn more about joins, please visit the article below,
Upvotes: 1