简体   繁体   中英

Joining Tables in MySQL Query instead of multiple queries

I have this query

$query = "SELECT * FROM items WHERE itemStatus = '1' AND itemAdded > '$timestamp'";

Once this query has returned results I loop through the results

the results array is itemID, itemLocationID, categoryParentID, categoryID, itemName, itemDetails

During the loop I then run three other queries by calling functions within the same class

$locationName = $this->getLocationByName($locationID);
$categoryParentName = $this->getCategoryByName($categoryParentID);
$categoryName = $this->getCategoryByName($categoryID);

the function getLocationByName performs this query;

$q = mysql_query("SELECT * FROM locations WHERE locationID = '$locationID'");

this returns an array of locationID, locationName, locationLink

the function getCategoryByName performs this query;

$q = mysql_query("SELECT * FROM categories WHERE categoryID = '$categoryID'");

this returns an array of categoryID, categoryName, categoryLink

Could someone please help me optimize this query and maybe join them to save doing so many queries.

thanks in advance.

Im now using this query

$q = mysql_query("SELECT 
i.itemID, 
i.locationID,
i.categoryParentID,
i.categoryID, 
i.itemName,
i.itemDetails,
l.*,
c.*        

FROM items i inner join locations l on i.locationID = l.locationID inner join categories c on i.categoryID = c.categoryID WHERE itemStatus = '1' AND itemAdded > '$timestamp'")or die(mysql_error());

and the result is

Array

( [itemID] => 81300 [locationID] => 17 [categoryParentID] => 21 [categoryID] => 183 [itemName] => blah [itemDetails] => blah [locationName] => brilliant it pulls in the location as expected. [locationLink] => blah [categoryName] => brilliant it pulls in the category as expected. [categoryLink] => blah )

[categoryName] => //these are missing for categoryParentID
[categoryLink] => //these are missing for categoryParentID

I think should be something similar to below query. I do not see where are you using $categoryParentName .

Using your queries and data:

SELECT * FROM items WHERE itemStatus = '1' AND itemAdded > '$timestamp'
SELECT * FROM locations WHERE locationID = '$locationID'
SELECT * FROM categories WHERE categoryID = '$categoryID'

$locationName = $this->getLocationByName($locationID);
$categoryParentName = $this->getCategoryByName($categoryParentID);
$categoryName = $this->getCategoryByName($categoryID);

Please let me know if this returns expected result set. Hope this helps

SELECT 
    it.itemID, it.itemLocationID, it.categoryParentID, it.categoryID, it.itemName, it.itemDetails,
    l.locationID, l.locationName, l.locationLink, 
    c.categoryID, c.categoryName, c.categoryLink
FROM items it 
LEFT JOIN locations l ON l.locationID = it.itemLocationID 
LEFT JOIN categories c ON c.categoryID = it.categoryID 
WHERE 
    it.itemStatus = '1' 
    AND it.itemAdded > '$timestamp'

Update query using categoryParentID - i am not saying is efficient but you can test and optimize as needed.

One option is to update above query - not sure that will work - and for large result sets using OR is not efficient:

LEFT JOIN categories c ON (c.categoryID = it.categoryID OR c.categoryID = it.categoryParentID)

The other option that i see is to get 2 result sets (see below) - one for categId = categId and second for categId = categParentId and combine the result set in one big result set.

SELECT 
    t.itemID, t.itemLocationID, t.categoryParentID, t.categoryID, t.itemName, t.itemDetails,
    l.locationID, l.locationName, l.locationLink, 
    t.categoryID, t.categoryName, t.categoryLink 
FROM 
(
SELECT 
    it.itemID, it.itemLocationID, it.categoryParentID, it.categoryID, it.itemName, it.itemDetails,
    c.categoryID, c.categoryName, c.categoryLink
FROM items it 
INNER JOIN categories c ON c.categoryID = it.categoryID 
WHERE 
    it.itemStatus = '1' 
    AND it.itemAdded > '$timestamp'

UNION -- [ALL]

SELECT 
    it.itemID, it.itemLocationID, it.categoryParentID, it.categoryID, it.itemName, it.itemDetails,
    c.categoryID, c.categoryName, c.categoryLink
FROM items it 
INNER JOIN categories c ON c.categoryID = it.categoryParentID 
WHERE 
    it.itemStatus = '1' AND 
    it.itemAdded > '$timestamp'
) AS t 
LEFT JOIN locations l ON l.locationID = t.itemLocationID 

Other idea - not tested and assuming that id are int - will have to cast as string / char. There are a few options how you can write this query - if you post a structure table and some dummy data i am sure that someone will create a demo / sqlfiddle.

SELECT 
    it.itemID, it.itemLocationID, it.categoryParentID, it.categoryID, it.itemName, it.itemDetails,
    l.locationID, l.locationName, l.locationLink, 
    c.categoryID, c.categoryName, c.categoryLink
FROM items it 
LEFT JOIN locations l ON l.locationID = it.itemLocationID 
WHERE 
    it.itemStatus = '1' 
    AND it.itemAdded > '$timestamp' 
    AND c.category ID IN ( SELECT GROUP_CONCAT(categs) FROM (SELECT CONCAT(categoryID, ",", categoryParentID) AS categs FROM items ))

I would not use * in the select statement The Query with the joins could be

SELECT 
    i.itemID, 
    i.itemLocationID,
    i.categoryParentID,
    i.categoryID, 
    i.itemName,
    i.itemDetails,
    l.*,
    c.*        
FROM 
    items i
    inner join locations l on i.itemLocationID = l.locationID
    inner join categories c on i.categoryID = c.categoryID
WHERE
    itemStatus = '1'
    AND itemAdded > '$timestamp'

I hope it be useful for you. Cheers!

Unless I'm missing something obvious, I'd probably suggest something like this as a first start:

select *
  from items i
  join locations l 
    on i.location_id=l.location_id
  join categories c
    on i.category_id=c.category_id
 where item_status='1'
   and itemAdded > '$timestamp'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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