Question

I am trying to return all info for products that the current user has purchased as long as those products are not in the product review table.

Right now, there is an Orders table, which holds all orders and contains the UserId.

There is an OrderItems table which contains all items ordered for each order (based on the OrderId) as well as the ProductId for each item.

However, there is also another table to check for orders that may have been made outside the store website (this table is called ApprovedProductReviews and contains a User Id field and a Product Id field)

Finally, there is the ProductReviews table which contains all submitted reviews for all products (and it contains the ReviewerProfileId (which is the same as the UserId) and the ProductId).

So far, I have been able to check to see if the current user has purchased a particular product with success:

SELECT [ProductId], [UserId] 
FROM [Orders] 
INNER JOIN [OrderItems] ON UserId= [current user id] 
  WHERE [ProductId] = [whatever the current product id is])
  OR [ProductId] IN 
     (SELECT [uidProduct] 
      FROM [ApprovedProductReviews] 
        WHERE [uidProduct]= [current user id])

But I am not sure how to alter this code to get check if a ProductId exists in the ProductReviews table. I suspect I may have to do a UNION but I am not sure...Any help would be appreciated!

To clarify some more, what I need to look at in the ProductReviews table is the ProductId and ReviewerProfileId (which is the same thing as the UserId. So, basically, ReviewerProfileId = UserId). I need to check to see if the ReviewerProfileId matches the current user's id, then I need to go through the Orders table to get the UserId, as well as the OrderItems table to get the ProductId, and I need to check in the ApprovedProductReviews table for the UserId and ProductId as well (this ApprovedProductReviews table may contain orders for a user that were placed outside of the site, hence, they will not appear in the Orders table but still count as valid orders).

So, I need to combine 3 tables just to get the proper UserId and ProductId information, and then I need to take the ProductId and see if it is in the ProductReviews table where UserId = ReviewerProfileId.

Hopefully, that all makes sense.

Was it helpful?

Solution 2

If I understand you correctly, you already have the first part of your set of data from this statement:

So, I need to combine 3 tables just to get the proper UserId and ProductId information, and then I need to take the ProductId and see if it is in the ProductReviews table where UserId = ReviewerProfileId.

To combine the two, here's one way of doing it in SQL Server (you didn't mention what flavor of SQL you are using):

;WITH UserProducts AS (
    SELECT [ProductId], [UserId] 
    FROM [Orders] 
    INNER JOIN [OrderItems] ON UserId= [current user id] 
    WHERE [ProductId] = [whatever the current product id is])
    OR [ProductId] IN 
        (SELECT [uidProduct] 
        FROM [ApprovedProductReviews] 
            WHERE [uidProduct]= [current user id])
)
SELECT
    P.*
FROM ProductReviews P
WHERE NOT EXISTS(
    SELECT *
    FROM UserProducts UP
    WHERE UP.ProductId = P.ProductId AND UP.UserId = P.ReviewerProfileId
)

This starts with what you already have: the user's list of products ordered as a common table expression (CTE), and then uses that to find entries in ProductReviews that don't have a corresponding hit.

If you aren't using a version of SQL that supports CTE's, then you could put your whole existing query inside the WHERE NOT EXISTS block, or use that to fill a temporary table (or table variable).

OTHER TIPS

You can use UNION and EXCEPT (which is the same as MINUS):

(
    SELECT OI.ProductID, O.UserID
    FROM
        Orders O
        INNER JOIN OrderItems OI
            ON O.OrderID = OI.OrderID
    WHERE
        O.UserID = @CurrentUser

    UNION

    SELECT APR.ProductID, APR.UserID
    FROM
        ApprovedProductReviews APR
    WHERE
        APR.UserID = @CurrentUser
)

EXCEPT

SELECT PR.ProductID, PR.ReviewerProfileID
FROM
    ProductReviews PR
WHERE
    PR.ReviewerProfileID = @CurrentUser

UNION returns only distinct values. If you need to return additional product and user information, you can use this query as a subquery and join the products and users table to it.

SELECT X.ProductID, P.ProductName, P.Number, X.UserID, U.UserName
FROM
    (<previous query>) X
    INNER JOIN Products P
        ON X.ProductID = P.ProductID
    INNER JOIN Users U
        ON X.UserID = U.UserID
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top