MS Access - Identify duplicates having minimum value - sql

I have a MS Access query which pulls [product name] and [price] along with several other fields. My problem is that I have multiple instances where [product name] is duplicated and [price] may or may not be the same between the duplicates. I'd like the query to show only one record for each of the duplicates and the minimum [price] associated with that [product name]....one big master list with no duplicates in it..... the final list should include all [product names] that didn't have duplicates and their associated price also.
I know this should be simple but for whatever reason I'm beating my brains out on it. I tried using a crosstab query already to return the minimum values for each unique [product name] but I have so many records that the crosstab query errors out on column count.
Any help would be greatly appreciated.
AC

MSAccess doesn't support Partition functions.
However, if you were able to get your data into a SQL database, you could easily do this using Window/Partition functions, which would allow you to do interesting things like select the cheapest 2 products, etc
SELECT *
FROM
(
SELECT ROW_NUMBER()
OVER (PARTITION BY [ProductName] ORDER BY [Price]) as RowNum, *
FROM Table
) X
WHERE RowNum = 1
You can now correctly get the actual row that was identified as the one with the lowest price and you can modify the ordering function to use multiple criteria, such as "Show me the latest product which had the cheapest score", etc.

Related

Aggregate my quantity sum in a way that doesn't lead to the storeID repeating?

I am writing a SQL query that needs to show the total number of orders from each store. The issue I am running into, is that while I can figure out how to sum the orders by product and each product is only sold by one store, I can't figure out how to total the orders by store alone
This is the code I currently have
SELECT storeID AS [STORE], Product_ID
, SUM(quantity) AS [ORDERS BY STORE]
FROM Fulfillment, Store
GROUP BY storeID, Product_ID;
This line of code leads to a repeat of storeID in the results, where ideally, I would only want storeID to be included in the results once with the total quantity of all of Product_ID being included. I tried to remove Product_ID from the GROUP BY statement, but this resulted in the following error
Column 'Fulfillment.Product_ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I'm new to SQL and am trying to learn, so any help and advice is greatly appreciated
#ZLK is correct that if your goal is a total number of units ordered ("quantity") of any product, simply remove the [product_id] column from the SELECT and GROUP BY.
However, it appears that you're referencing two tables ("FROM Fulfillment, Store") and not specifying how those tables are joined, creating a cartesian join - all rows in one table will be joined to all rows in the other table. If the [storeID] and [quantity] fields are available in the Fulfillment table, I recommend removing the Store table reference from the FROM clause (so "FROM Fulfillment" alone).
One last note: You mention that you want to count "orders". In some circumstances, an order may have multiple products and a quantity > 1. If your goal is the total number of "orders" regardless of the number of products or quantity of products on an order, you'll want to use "COUNT(DISTINCT orderID) as [Orders]" (where "orderID" is the reference to the unique order number).

SQL Loop Distinct Values for Use in Calculated Columns

I am trying to do something in SQL here. I have a product type, lets call it "Food" and I have a table with names of stores, product types, and product names, let's call the stores, "Red, Blue, Green". I want to run a query that finds every store in which Product Type "Food" was sold.
So something like this:
SELECT DISTINCT [Stores]
FROM dbo.SalesTable
WHERE [Product Type] = 'Food'
Then I want to use each distinct store name in a loop, to populate calculated columns telling me the sales numbers of each product type in the individual stores. The actual Product Type could be many things and each would have a unique list of stores. So I will probably declare the VARCHAR variable for use in the query.
Basically I think column A would be product Names for the product type used, and columns 2 through X would be the sales of each product at each store. If there were 5 stores then those calculations would sit in columns 2 through 6.
I just have no experience using loops in SQL and hopefully somebody can help out. Thanks so much!!
Grouping is going to be your key here.
SELECT [Product Type], Stores, SUM(SalesTable.column1), COUNT(SalesTable.column2) ...
FROM SalesTable
GROUP BY [Product Type], Stores

How to work past "At most one record can be returned by this subquery"

I'm having trouble understanding this error through all the researching I have done. I have the following query
SELECT M.[PO Concatenate], Sum(M.SumofAward) AS TotalAward, (SELECT TOP 1 M1.[Material Group] FROM
[MGETCpreMG] AS M1 WHERE M1.[PO Concatenate]=M.[PO Concatenate] ORDER BY M1.SumofAward DESC) AS TopGroup
FROM MGETCpreMG AS M
GROUP BY M.[PO Concatenate];
For a brief instance it reviews the results I want, but then the "At most one record can be returned by this subquery" error comes and wipes all the data to #Name?
For context, [MGETCpreMG] is a query off a main table [MG ETC] that was used to consolidate Award for differing Material Groups on a PO transaction ([PO Concatenate])
SELECT [MG ETC].[PO Concatenate], Sum([MG ETC].Award) AS SumOfAward, [MG ETC].[Material Group]
FROM [MG ETC]
GROUP BY [MG ETC].[PO Concatenate], [MG ETC].[Material Group]
ORDER BY [MG ETC].[PO Concatenate];
I'm thinking it lies in my inability to understand how to utilize a subquery.
In the case in which the query can return more then one value? Simply add an additonal sort by.
So, a common sub query might be to get the last invoice. So you might have:
select ID, CompanyName,
(SELECT TOP 1 InvoiceDate from tblInvoice
where tblInvoice.CustomerID = tblCompany.ID
Order by InvoiceDate DESC)
As LastInvoiceDate
From tblCustomers
Now the above might work for some time, but then it will blow up since you might have two invoices for the same day!
So, all you have to do is add that extra order by clause - say on the PK of the child table like this:
Order by InvoiceDate DESC,ID DESC)
So top 1 will respect the "additional" order columns you add, and thus only ever return one row - even if there are multiple values that match the top 1 column.
I suppose in the above we could perhaps forget the invoiceDate and always take the top most last autonumber ID, but for a lot of queries, you can't always be sure - it might be we want the last most expensive invoice amount. And again, if the max value (top) was the same for two large invoice amounts, then again two rows could be return. So, simply add the extra ORDER BY clause with an 2nd column that further orders the data. And thus top 1 will only pull the first value. Your example of a top group is such an example. Just tack on the extra order by "ID" or whatever the auto number ID column is.

Whats the difference between these two SQL queries?

Question: Select the item and per unit price for each item in the items_ordered table. Hint: Divide the price by the quantity.
1.
select item, sum(price)/sum(quantity)
from items_ordered
group by item;
2.
select item, price/quantity
from items_ordered
group by item;
Have a look at the resultis for flashlights. First one shows average price correctly but 2nd one only takes 28/4 and shows 7, ignoring the 4.5 few rows down. Someone please explain why this is the case.
The used table data from an external website.
SUM() is a group function - so that essentially says go get me all the price and quantities by item, and add them all up to return them in one row.
MySQL is quite forgiving when grouping things and will try to retrieve a rowset (which is why your second example returns something - albeit wrong).
Generally, if you are GROUPing columns (items in your exmaple), you need to return one row per column (item).
Try running the SQL below to see what that looks like.
SELECT item
, SUM(price) AS sum_price
, SUM(quantity) AS sum_quantity
, COUNT(*) AS item_count
, SUM(price) / SUM(quantity) AS avg_price_per_quant
FROM items_ordered
GROUP BY item
ORDER BY item ASC
The first query returns the average price for that item, the second query returns the price for the first item it encounters. This only works in MySQL, the second query would error in SQL Server as no aggegrate function is used. See this post for more details Why does MySQL allow "group by" queries WITHOUT aggregate functions?.

JOIN on Access "Lookup" field returns no results

I have a strange problem that I believe is related to the way my lookups are structured.
TABLE Category
ID
CategoryName
TABLE Product
ID
ProductName
Category - Number (SELECT [Category].[ID], [Category].[Category Type] FROM Category ORDER BY [Category Type];)
TABLE SalePrices
Several fields related to sale date, price, &c.
ProductName - Text (SELECT [Product].[ID], [Product].[Product Name] FROM Product ORDER BY [Product Name];
For some reason I get a blank result set when I run the following query:
SELECT SalePrices.[Product Name], Product.[Product Name]
FROM SalePrices INNER JOIN Product ON SalePrices.[Product Name] = Product.[Product Name];
I have a query that displays the MIN of SalePrices.UnitPrice which I want to display with the ProductName and CategoryName, but I'm not getting results for that so I wanted to simplify things first.
When I join Product and Category I have to match Product.[Category Type] = Category.ID;, but when I try to do SalePrices.[Product Name] = Product.[ID]; I get a TYPE MISMATCH error. I'm not sure where I went wrong.
The eventual goal is to combine the SalesPrices <-> ProductName join with this one:
SELECT Product.[Product Name], Category.[Category Type]
FROM Product INNER JOIN Category ON Product.[Category Type] = Category.ID;
As suggested in the comments by #Scotch and #HansUp, defining "Lookup" fields in an Access table is generally regarded as a Bad Idea for all but the most trivial of cases. They hide what is really going in the database and they can lead to all kinds of confusion (as you have discovered) when you actually try to use them. (Ref: here, via comment by #HansUp.)
Your best course of action would be to replace the Lookup fields in your tables with regular numeric fields containing the ID (key) values in the related tables. Then, if necessary, you can create and save Select Queries to explicitly do the lookups and display the results as they previously appeared in the [Product] and [SalePrices] Datasheet Views.