简体   繁体   中英

Faster way of performing this SQL query

I have a large SQL table that stores an added item id that the user added to their profile and the rating they gave it. The thing is, I need to quickly count how many times an item has been added AND also need to get the total ratings it was given. Sometimes the rating may or may not be null depending on whether or not the user left a rating for the item. The table looks something like this

Item_Feedback_ID (Pri, AI)  Item ID    Item Rating    User_ID_Added
     1                        5          Null               4
     2                        5           8                 5         
     3                        6           9                 9 

I need to do this for every unique item ID there is (I already have a table that stores unique Item IDs). What I'm currently doing now is this:

PSEUDO PHP CODE:
$result = the result of: "SELECT item_id FROM items";
foreach ($item_id in $result) {
    $sql = "SELECT COUNT(item_id) as sum, SUM(`Item Rating`) as total_rating FROM 
            item_feedback WHERE item_id = $item_id";
//Run that sql statement in PHP and parse it and save in an array
}

Is there a more efficient way of doing this? It seems as though I waste lots of time as COUNT already scans through all the columns and I have to do this again for x number of item ids.

You should be able to accomplish this one one query with a subquery for the optional data. I'm using a LEFT JOIN for the extra data so that items that don't have that data will still be returned. The reason for the subquery is because you're using COUNT . Without the subquery, that would count ALL of the records, and not just the records that have feedback.

SELECT 
  items.item_id,
  feedback.sum,
  feedback.total_rating
FROM items
LEFT JOIN(
  SELECT
    item_id,
    COUNT(item_id) as sum,
    SUM(`Item Rating`) as total_rating
    FROM item_feedback
    GROUP BY item_id
) AS feedback ON feedback.item_id = items.item_id
$sql = "SELECT ifnull(t.count, 0) as count, 
               ifnull(t.total_rating, 0) total_rating, 
               a.item_id 
        FROM items a
        left join (SELECT COUNT(item_id) as count,
                          SUM(`Item Rating`) as total_rating,
                          b.item_id  
                     from item_feedback b
                     group by b.item_id) t on t.item_id = a.item_id " ;

I'm no expert in PHP but maybe you could throw the data into a temp table and then loop through it. Maybe somthing like this for your SQL script.

INSERT INTO TempTable
SELECT 
    COUNT(item_id) as sum, 
    SUM(`Item Rating`) as total_rating 
FROM item_feedback
GROUP BY item_id

Then loop through your TempTable by item_id

If you don't need a row for every Item, then just a query on item_feedback is sufficient, and use of the SQL CASE statement will help you out as well:

select 
item_id,
count(*) as item_added_count,
sum(case when [item rating] is not null then 1 else 0 end) as rating_count
from item_feedback
group by item_id

If you DO need a row for every item, and want to show 0's when the item has never been added to the item_feedback table, then use a LEFT OUTER JOIN with the items table:

select 
i.item_id,
sum(case when f.item_id is not null then 1 else 0 end) as item_added_count,
sum(case when f.[item rating] is not null then 1 else 0 end) as rating_count
from items i
left outer join item_feedback f on f.item_id = i.item_id
group by i.item_id

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