GROUP BY and SUMS in MS ACCESS - sql

I'm trying to get a report of how many article have been sold, especially which one was sold more, both in terms of numbers and price.
I'm trying the above query, thinking that using the [PRICE]*[total] in the group by expression, it could worked. unluckily it does not. I've try also to put the alias in the group by expression, but nothing more, it only says that I need to use a grouping expression for the column: [PRICE]*[total] which is what I thought I have done.
SELECT TOP 20 ARTIC, Sum(TOTGIA) AS total, [PRICE]*[total] AS a
FROM Car
GROUP BY ARTIC, [PRICE]*[total]
ORDER BY Sum(TOTGIA) DESC;
anyone could lead me in the good direction?
the error is:
"You tried to execute a query that does not include the specified expression '[PRICE]*[total]' as part of an aggregate function."
the table is something like this:
|artic|totgia|price
+++++++++++++++++++
|aaa | 1 | 10
|aaa | 4 | 10
|bbb | 1 | 200
I would like to have:
|aaa| 5 | 50
|bbb| 1 | 200
so aaa is the first one for number of sells, but bbb is first for cash

The problem here is that you are trying to use the total alias in the select and in the group by. You do not have access to the alias at this time. Instead, you will either need to refer to the actual column values in place of total. In other cases, you can create a subselect and use the alias, but this does not apply to your query as it is written.
SELECT TOP 20 ARTIC, Sum(TOTGIA) AS total, PRICE*Sum(TOTGIA) AS a
FROM Car
GROUP BY ARTIC, PRICE
ORDER BY Sum(TOTGIA) DESC;
If you have an article listed with several different prices, this query will return several rows. So, this data:
|artic|totgia|price
+++++++++++++++++++
|aaa | 1 | 10
|aaa | 4 | 20
|bbb | 1 | 200
Would return these results:
|aaa| 1 | 10
|aaa| 4 | 80
|bbb| 1 | 200
This would happen because we have specifically told sql that we want the unique articles and prices as their own rows. However, this is probably a good thing because in the above scenario, you wouldn't want to return that aaa has a quantity of 5 with a value of 50, since the total value is 90. If this is a possible scenario for your data, you would make this query into a subselect and group all the data for the unique articles together.

Related

MS Access | Find Top Combinations

I have searched google/stack to find the right answer, but what I have tried so far is not working.
Here is the problem:
I have created a table with several combinations. I am trying to find the combination that minimizes total cost.
As an example, the table looks something like this:
Combo ID | Combination | Cost
1 | 345678 | 15
2 | 345678 | 15
3 | 345678 | 18
4 | 456343 | 12
5 | 456343 | 13
So: for the combination 345678, ID #1 and #2 both minimize the cost and #4 minimizes the cost for the 456343 combination. So hopefully the query can return either the IDs 1,2,4 or it can simply return the total cost that is the minimum for that combination eg { (345678, 15), (456343, 12) }
If you want to get the IDs, you have to have a sub query that first gets the Min cost. Then you can match the combination and cost to the original Table.
SELECT Table1.ID, Table1.Combo, Table1.Cost
FROM Query1 INNER JOIN Table1 ON (Query1.MinOfCost = Table1.Cost) AND (Query1.Combo = Table1.Combo)
Query 1 :SELECT Table1.Combo, Min(Table1.Cost) AS MinOfCost FROM Table1 GROUP BY Table1.Combo

Return all rows that match column 1 of a row selected by criteria in column 2

Unfortunately, I think I'm quite limited in what solutions I can apply. I'm doing this for work and I only have permissions to SELECT from tables through Access 2010. I can't update or create tables. I can't find useful information like what version of sql is on the backend, let alone access the database directly or use VBA.
Say we have a dataset like this (crude looking, sorry):
MemberID | StatusCd | Date Added
12345 | 200 | 08/01/2016
12345 | 300 | 09/01/2016
12345 | 400 | 10/01/2016
5646 | 400 | 10/01/2016
8946 | 100 | 07/01/2016
Now, this database is massive and it'll be a huge performance issue if I try to pull all members in the table and process it afterwards. What I want is to return all rows that share a MemberID where at least one row for that MemberID is StatusCd 300. For instance, if I wanted information about members that hit Status 300, the desired table would look like:
MemberID | StatusCd | Date Added
12345 | 200 | 08/01/2016
12345 | 300 | 09/01/2016
12345 | 400 | 10/01/2016
However, right now when I try use a SELECT command that uses WHERE StatusCd = 300, I only get the one row where that condition is met. I don't know if it will interfere with anything, but I'm currently joining this table to another table on the memberID to get a smaller, more relevant table set to work with. It would also be nice to omit rows that come prior to the StatusCd 300, but that's a small chunk of extra data that won't hurt too much to leave in.
Thanks for any help anybody can provide!
Edit: adjusted phrasing based on comment feedback.
To get all rows for a member where at least 1 row has a statuscd of 300 first select all the corresponding memberid with a sub-query then select everything with that memberid from the table:
select *
from t
where memberid in (
select memberid from t where statuscd = 300
)

Alternating positive and negative numbers

I created a SQL Server database and there is a table "COST OF PRODUCTS" (> 600,000 rows). I have to make a query that shows which products have changed the price. As you can see below: 1,2,3 rows, because 1st is positive and 2nd is negative; 3rd is positive. As I understand, I must create an additional table and check using inner join or use Lag/Lead function.
Who knows what's the better way to do it?
ID | COST | CHANGE
1 | 450 | 1,4
2 | 350 | -0,8
3 | 470 | 1,2
4 | 550 | 1,3
If you just want the data listed with positive first, and then negative you can either do:
SELECT * FROM COST_OF_PRODUCTS
WHERE CHANGE>0
UNION
SELECT * FROM COST_OF_PRODUCTS
WHERE CHANGE<0
Or
SELECT * FROM COST_OF PRODUCTS
ORDER BY CHANGE

SQL payments matrix

I want to combine two tables into one:
The first table: Payments
id | 2010_01 | 2010_02 | 2010_03
1 | 3.000 | 500 | 0
2 | 1.000 | 800 | 0
3 | 200 | 2.000 | 300
4 | 700 | 1.000 | 100
The second table is ID and some date (different for every ID)
id | date |
1 | 2010-02-28 |
2 | 2010-03-01 |
3 | 2010-01-31 |
4 | 2011-02-11 |
What I'm trying to achieve is to create table which contains all payments before the date in ID table to create something like this:
id | date | T_00 | T_01 | T_02
1 | 2010-02-28 | 500 | 3.000 |
2 | 2010-03-01 | 0 | 800 | 1.000
3 | 2010-01-31 | 200 | |
4 | 2010-02-11 | 1.000 | 700 |
Where T_00 means payment in the same month as 'date' value, T_01 payment in previous month and so on.
Is there a way to do this?
EDIT:
I'm trying to achieve this in MS Access.
The problem is that I cannot connect name of the first table's column with the date in the second (the easiest way would be to treat it as variable)
I added T_00 to T_24 columns in the second (ID) table and was trying to UPDATE those fields
set T_00 =
iif(year(date)&"_"&month(date)=2010_10,
but I realized that that would be to much code for access to handle if I wanted to do this for every payment period and every T_xx column.
Even if I would write the code for T_00 I would have to repeat it for next 23 periods.
Your Payments table is de-normalized. Those date columns are repeating groups, meaning you've violated First Normal Form (1NF). It's especially difficult because your field names are actually data. As you've found, repeating groups are a complete pain in the ass when you want to relate the table to something else. This is why 1NF is so important, but knowing that doesn't solve your problem.
You can normalize your data by creating a view that UNIONs your Payments table.
Like so:
CREATE VIEW NormalizedPayments (id, Year, Month, Amount) AS
SELECT id,
2010 AS Year,
1 AS Month,
2010_01 AS Amount
FROM Payments
UNION ALL
SELECT id,
2010 AS Year,
2 AS Month,
2010_02 AS Amount
FROM Payments
UNION ALL
SELECT id,
2010 AS Year,
3 AS Month,
2010_03 AS Amount
FROM Payments
And so on if you have more. This is how the Payments table should have been designed in the first place.
It may be easier to use a date field with the value '2010-01-01' instead of a Year and Month field. It depends on your data. You may also want to add WHERE Amount IS NOT NULL to each query in the UNION, or you might want to use Nz(2010_01,0.000) AS Amount. Again, it depends on your data and other queries.
It's hard for me to understand how you're joining from here, particularly how the id fields relate because I don't see how they do with the small amount of data provided, so I'll provide some general ideas for what to do next.
Next you can join your second table with this normalized Payments table using a method similar to this or a method similar to this. To actually produce the result you want, include a calculated field in this view with the difference in months. Then, create an actual Pivot Table to format your results (like this or like this) which is the proper way to display data like your tables do.

MS Access sum of 2 table in one query

I have 2 tables:
name "mfr"
name "pomfr"
Both have many columns, but some are same, and I want to sum of that similar column in one query based on one of them similar column group by
Data sample is
table1. mfr
rfno|ppic|pcrt
101 | 10| .30
102 | 15| .50
103 | 18| .68
table2 pomfr
rfno|ppic|pcrt
101 |100 | 1.15
102 | 50 | 1.50
103 | 0 | 0
and result in query should be
mfrquery
rfno|ppic|pcrt
101|110 |1.45
102| 65 |2.00
103| 18 | .68
I'll be somewhat nice. This probably isn't the most efficient method, but it'll work...
select* into #temp from table1
union
select* from table2
select id,sum(ppic) as ppic, sum(pcrt) as pcrt from #temp group by id
What this says is, select everything from table 1 and use a union to table two and place it in a temporary table called #temp. Filter this to the variables and ranges you need.
Then the 2nd part says, take the sum of ppic and the sum of pcrt from the #temp table and group it by the id.
Since you're new to SO, for future reference, SO people aren't mean, they just want to see you put forth some sort of effort into the problem, I've gotten help SEVERAL times here. Very helpful community! Best of luck to you!