Return unique items in SQL query - mysql

SELECT Product.name, Product.price
FROM Purchased, Product
WHERE Purchased.date1 > '2013-11-02'
ORDER BY price DESC group by Product.name
Hello I am writing a query to return a list of unique products that were bought retailer’s site since November the 2nd with most expensive product returned first.
Can anyone tell me what is wrong with my syntax?

You are using MySQL's group by extension incorrectly. Although MySQL allows you to put items in the select list that are not in the group by or an aggregate, it is not deterministic and ORDER BY will not help this.
The MySQL documents state:
The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause.
So even if your data was like:
ProductName | Price
------------+----------
A | 2.50
A | 3.50
B | 9.99
Using GROUP BY Product.Name ORDER BY Price DESC is not guaranteed to return the highest price for each product. i.e.
ProductName | Price
------------+----------
A | 3.50
B | 9.99
What you are really saying is "give me one price per product (any price), then order the final results by price". So you could just as easily get 2.50 as the price for product A. I think you could get the results you want by using ``MAX`:
SELECT product.name,
Max(product.price) AS Price
FROM purchased,
product
WHERE purchased.date1 > '2013-11-02'
GROUP BY product.name
ORDER BY price DESC;
I suspect you are also missing a relation between product and purchased, this would be avoided if you used the newer ANSI 92 explicit join syntax, the implicit join syntax you are using is 20 years out of date:
So your final query would be something like:
SELECT product.name,
Max(product.price) AS Price
FROM purchased
INNER JOIN product
ON product.id = purchased.productid
WHERE purchased.date1 > '2013-11-02'
GROUP BY product.name
ORDER BY price DESC;
N.B. I have had to guess at the relationship between Product and Purchased

SELECT
p.name AS Name,
MAX(p.price) AS Price
FROM Purchased AS pr
INNER JOIN Product AS p
ON pr.ProductId=p.ProductId
WHERE pr.date1 > '2013-11-02'
GROUP BY p.name
ORDER BY p.price DESC
I suppose that both your tables, Purchased and Product, have a productId column. This way each record to one table will relate with another record to the other table. If this is not the name of this column, please change the ProductId to the corresponding name.

The first thing you will need to do is find out how the tables are related to one another. I'm going to assume that you have a productid column in your purchased table.
SELECT Product.name, Product.price
FROM Purchased, Product
where Purchased.productid = product.id
and Purchased.date1 > '2013-11-02'
ORDER BY price DESC
What we are doing here is joining the two tables by the id column they have in common. By doing this the database knows what data links together.
Lets say we have the
purchase table
PurchaseDate , Productid,
2013-11-02 1
2013-11-03 2
Product table
id , Product name
1 Fuzzy Bunny
2 Fuzzy bear
Now if you look at that data you know that on 2013-11-02 fuzzy bunny was purchased. You can see this because the productid on your purchase table links back to the id on the product table. That's how you figure out how to work with Joins in SQL.

Referring to your previous question.
SQL Structure help and query
Here is the sqlfiddle
In the query,
group by should be before the order by clause.
SELECT product.name,
product.price
FROM purchased,
product
WHERE purchased.date1 > '2013-11-02'
GROUP BY product.name
ORDER BY price DESC;

Can you please try this:
SELECT Product.name, Product.price
FROM Purchased, Product
WHERE Purchased.date1 > '2013-11-02'
ORDER BY price DESC GROUP BY Product.name,Prodcut.price
When you are using GROUP BY , you must include all the columns that you are retrieving in select class.
Hope this helps.

Related

MySQL - Average number of particular product sold on date

I need to write SQL query for "average number of particular product sold by date. On each day is sold min one product".
SELECT AVG (COUNT (PID))
FROM SOLD
GROUP BY DATE, PID;
P.S. PID means Product ID.
Is this query okay?
Should this give right answer?
Consider Using distinct count of date columns
SELECT PID,
COUNT(PID)/COUNT(distinct date_) as "Avg.Product Sold By Days"
FROM SOLD
GROUP BY PID;
You can try this sql query below. Basically, it will return the average number of 'SALES' for each product you have. It will group by each distinct product ID. Please provide us the data structure your of table and etc.
SELECT product_ID, trans_date
Sum(sales_of_product) / COUNT(DISTINCT sold_transaction) AS 'avg'
FROM SOLD
GROUP BY product_ID

Choosing Correct Dates

Please excuse my formatting... I am working on that.
I am trying to select the correct price of a project in my query based off the appropriate effective date.
For example we have a table that has the following information
Price Table-------------------------
Item Price effectiveDate
A $0.57 1/1/17
A $0.72 6/1/17
Now I have a production table that contains what was produced that day and it will list out their quantity and the production for a production date.
Production Table-------------------
Item Quantity productionDate
A 100 2/1/17
A 100 7/1/17
Now when I query these I want to be able to select the appropriate price given the productionDate and effectiveDate.
What is the best way to achieve this?
Try the following (first select the highest effectiveDate lower than the productionDate, then get the price for that date):
SELECT preselection.Item, Price FROM
(SELECT Production.Item, Max(effectiveDate) As MaxEffectiveDate
FROM Production INNER JOIN Price ON Price.item = Production.Item
Where Price.effectiveDate <= productionDate GROUP BY Production.Item) As preselection
INNER JOIN Price ON Price.Item = preselection.Item
AND Price.effectiveDate = preselection.MaxEffectiveDate

Constraints on group by

I have a products table that contains all the products that can be sold by a seller. It has two columns as primary key; product_code and amount(product weight basically).
As product weight varies their price varies. 6 types of product weight are available: 0.5, 1, 1.5, 2, 2.5, 3. Product code for a product having different weights would be the same.
Sample data:
product_code | product_quantity | amount | quantity
1234 | 6 | 0.5kg | 0
1234 | 6 | 1.0kg | 7
1234 | 6 | 1.5kg | 8
I want to display all products, but only once per product_code.
SELECT * FROM products where group by product_code
Given the above three rows, this query gives me the first row of the three.
However, I want to return rows with quantity greater than zero if they exist, otherwise any row will do.
What modification do I need to make in my query to achieve this?
Here's my table structure:
If you want one row per product_code with the highest quantity you can use a WHERE condition with a correlated subquery, that is sorted by quantity and limited to one row.
SELECT p1.*
FROM products p1
WHERE (p1.product_code, p1.amount) = (
SELECT p2.product_code, p2.amount
FROM products p2
WHERE p2.product_code = p1.product_code
ORDER BY p2.quantity DESC
LIMIT 1
)
You need to use the primary key for the condition. But because we have WHERE p2.product_code = p1.product_code in the subquery, we can also rewrite it to:
SELECT p1.*
FROM products p1
WHERE p1.amount = (
SELECT p2.amount
FROM products p2
WHERE p2.product_code = p1.product_code
ORDER BY p2.quantity DESC
LIMIT 1
)
Now MySQL should be able to cache the subquery result for each product_code. With an index on (product_code, quantity, amount) or just (product_code, quantity) the subquery should be executed pretty fast.
To keep the result deterministic you can extend the ORDER BY clause of the subquery. If two rows with the same product_code have the same quantity and you want to pick the one with the greater amount (which cann't be equal because it's part of the primary key) then use
ORDER BY p2.quantity DESC, p2.amount DESC
Bearing in mind that you're using a non-standard feature, ie grouping by a subset of the non-aggregated columns, in which case (not guaranteed) the first row is returned for each group...
Do the group by over an ordered rowset that encounters non-zero quantities before zero quantities:
SELECT * FROM (
SELECT * FROM products
ORDER BY quantity desc
) x
GROUP BY product_code
Note: The implementation you're using behaves this way, but no guarantees are given that future versions will continue to work reliably the way you want them to.
Also, as per the documentation:
As of MySQL 5.7.5, the default SQL mode includes ONLY_FULL_GROUP_BY.
This means that your query won't run on 5.7.5+ unless you actively disable ONLY_FULL_GROUP_BY after installing.
The reliable, and portable, way is to use a subquery that finds all the desired quantities and joins to that. But you have the added complication that the quantity is not unique to a product, so you have to break the tie using amount:
SELECT p.*
FROM products p
JOIN (SELECT p2.product_code, max_quantity, max(amount) max_amount
FROM products p2
JOIN (SELECT product_code, MAX(quantity) max_quantity
FROM products
GROUP BY product_code) q
ON q.product_code = p2.product_code
AND max_quantity = p2.quantity
GROUP BY product_code, max_quantity) qa
ON p.product_code = qa.product_code
AND quantity = max_quantity
AND amount = max_amount
The first subquery finds the max quantity (which is the data you want), then the next subquery finds the max amount of all rows with that max quantity (there could be more than one row sharing the max amount). Since the combination of product code, amount and quantity is unique, joining back to the table using these values with give you the rows you want.
Disclaimer: Code may not compile or work as it was thumbed in on my phone (but there's a reasonable chance it will work)

MYSQL - SUM of a column based on common value in other column

I'm stuck on crafting a MySQL query to solve a problem. I'm trying to iterate through a list of "sales" where I'm trying to sort the Customer IDs listed by their total accumulated spend.
|Customer ID| Purchase price|
10 |1000
10 |1010
20 |2111
42 |9954
10 |9871
42 |6121
How would I iterate through the table where I sum up purchase price where the customer ID is the same?
Expecting a result like:
Customer ID|Purchase Total
10 |11881
20 |2111
42 |16075
I got to: select Customer ID, sum(PurchasePrice) as PurchaseTotal from sales where CustomerID=(select distinct(CustomerID) from sales) order by PurchaseTotal asc;
But it's not working because it doesn't iterate through the CustomerIDs, it just wants the single result value...
You need to GROUP BY your customer id:
SELECT CustomerID, SUM(PurchasePrice) AS PurchaseTotal
FROM sales
GROUP BY CustomerID;
Select CustomerID, sum(PurchasePrice) as PurchaseTotal FROM sales GROUP BY CustomerID ORDER BY PurchaseTotal ASC;
Just by having a little Google search, I managed to find a page doing exactly what you're doing (I think). I have tailored the query below to fit your circumstance.
SELECT CustomerID, SUM(PurchasePrice) AS PurchaseTotal
FROM sales
GROUP BY CustomerID
ORDER BY PurchaseTotal ASC
Link to Page with Tutorial on SQL Groups

In a product database, How to calculate pricechange from two periods, and group by category

hi have a product database which the price is changing every month (period) - I want to show the price-change in percent, grouped by category. The schema is something like this: id, name, category, price, period. (The period is YYYY-MM)
A rows could be:
123, "Chair" , "Furniture", 123 , 2013-05 -- for may
123, "Chair" , "Furniture", 110 , 2013-06 -- for june
Is it possible in a SQL-query to calculate the percentage difference for each product for each month? And at the same time group categories together?
The challenge in this sort of query is finding the previous period. Here is one approach:
select p.*,
(p.price -
(select p2.price
from product p2
where p2.id = p.id and p2.period < p.period
order by period desc
limit 1
) - 1
) * 100 as PercentageChange
from product p
order by category;
It uses a correlated subquery and it makes the assumption that there is a price by every month. By "group categories together", I assume you mean to sort by the category. (Aggregating by the category would lose the information about each product.)
Note that the above syntax could vary by database. Different databases have different way of limiting the results to one row.