Select top n (variable) for each criteria in a table based on another table - sql

I want a VBA code to make a query to show Equip with Top ActiveTime for each ModelID (from 1st table) based on TopN for each ModelID (from the 2nd table), I know i have to use QueryDef and Sql VBA but I can't figure how to write the code
Just and Example to illustrate
My 1st table is
EquipID
Equip
ActimeTime
ModelID
1
DT1
10
1
2
DT2
6
1
3
DT3
13
1
4
DT4
15
1
5
DT5
16
2
6
DT6
12
2
7
DT7
6
2
8
DT8
13
2
My 2nd Table is
ModelID
Model
TopN
1
775
3
2
789
2
So the query result should be like (Showing the Top 3 of 775 Model and the Top 2 of 789)
Equip
ActimeTime
Model
DT4
15
775
DT3
13
775
DT1
10
775
DT5
16
789
DT8
13
789
Thanks a lot in advance, I'm really stuck at this one and solving this will help me a lot in my project
[Table1][1]
[1]: https://i.stack.imgur.com/geMca.png
[Table2][2]
[2]: https://i.stack.imgur.com/lMPDP.png
[Query Result][3]
[3]: https://i.stack.imgur.com/cGf6k.png

You can do it in straight SQL - but oooh is it ugly to follow and construct
I created 4 queries with the final one resulting in what you're looking for.
The key was to get a RowID based on the sorted order you're looking for (Model and ActimeTime). You can get a pseudo Row ID using Dcount
Here's the 4 queries - I'm sure you can make one mashup if you're daring
My tables are Table3 and Table4 - you can change them in the first query to match your database. Build these queries in order as they are dependent on the one before them
qListModels
SELECT Table3.Equip, Table3.ActimeTime, Table4.Model, Table4.TopN, "" & [Model] & "-" & Format([ActimeTime],"000") AS [Model-ActTime]
FROM Table3 INNER JOIN Table4 ON Table3.ModelID = Table4.ModelID
ORDER BY Table4.Model, Table3.ActimeTime DESC;
qListModelsInOrder
SELECT qListModels.*, DCount("[Model-ActTime]","[qListModels]","[Model-ActTime]>=" & """" & [Model-ActTime] & """") AS row_id
FROM qListModels;
qListModelStartRows
SELECT qListModelsInOrder.Model, Min(qListModelsInOrder.row_id) AS MinOfrow_id
FROM qListModelsInOrder
GROUP BY qListModelsInOrder.Model;
qListTopNModels
SELECT qListModelsInOrder.Equip, qListModelsInOrder.ActimeTime, qListModelsInOrder.Model
FROM qListModelsInOrder INNER JOIN qListModelStartRows ON qListModelsInOrder.Model = qListModelStartRows.Model
WHERE ((([row_id]-[MinOfrow_id])<[TopN]))
ORDER BY qListModelsInOrder.Model, qListModelsInOrder.ActimeTime DESC;
This last one can be run anytime to get the results you want
Example Output:

Related

MS-Access UPDATE statistics per person

Ive got this update query that uses employee activity stored in two tables (Beldata_filter & Urenlog_filter) to create a performance analysis per employee in another table (Bellers_filter).
however, i cannot get my query to update the performance stats per employee using only the activities of that employee in the other two tables, instead, access updates the stats per employee to the total activities of all employees.
here is the update query that i have written, the '.Beller' and '.Naam' signify columns in the tables with the names of the employees that i would like access to distinguish from one another.
UPDATE (Bellers_Filter INNER JOIN Urenlog_Filter ON Bellers_Filter.Naam=[Urenlog_Filter].Naam) INNER JOIN Beldata_Filter ON Bellers_Filter.[Naam]=[Beldata_Filter].Beller SET
Bellers_Filter.[Num b] = Dcount("[Beller]","[Beldata_Filter]"),
Bellers_Filter.[Num o] = Dcount("[Opgenomen]","[Beldata_Filter]","Opgenomen = 1"), Bellers_Filter.[Num nno] = Dcount("[Actie]","[Beldata_Filter]","Actie = 3"),
WHERE ([Beldata_Filter].Beller=[Urenlog_Filter].Naam);
The source table Beldata_filter looks like this:
Beller
ID
Moment
Opgenomen
Actie
Robert
55
8-11-2022
1
1
Susan
56
8-11-2022
1
1
Robert
55
9-11-2022
1
2
Robert
55
9-11-2022
0
3
Susan
56
9-11-2022
1
1
in this table each observation describes an action conducted by an employee. The other source table Urenlog_filter has got the same format, in this case the significance of the data in the tables is not as important as the observations of the data.
The table that will be updated needs to look like this
Id
Naam
Num b
Num o
Num nno
1
Robert
3
2
1
2
Susan
2
2
0
This is the desired result in its most simple form, the update query recognises 3 observations for robert and 2 for Susan under "Num b". Right now, the table looks like this
Id
Naam
Num b
Num o
Num nno
1
Robert
5
4
1
2
Susan
5
4
1
Who can help me with this problem? If you guys need more info please let me know!
Saving aggregate data is usually unnecessary and bad design. If it can be calculated for UPDATE, it can be calculated when needed.
SELECT Beldata_Filter.ID, Beldata_Filter.Beller,
Count(Beldata_Filter.Moment) AS [Num n],
Count(IIf([Opgenomen]=1,[Opgenomen],Null)) AS [Num o],
Count(IIf([Actie]=3,[Actie],Null)) AS [Num nno]
FROM Beldata_Filter
GROUP BY Beldata_Filter.ID, Beldata_Filter.Beller;
However, if you really must save, I don't see need for JOINing tables.
Include filter criteria in DCount() for names.
UPDATE Bellers_Filter SET
[Num b] = DCount("*","Beldata_Filter","Beller='" & [Naam] & "'"),
[Num o] = DCount("*","Beldata_Filter","Beller='" & [Naam] & "' AND Opgenomen=1"),
[Num nno] = Dcount("*","[Beldata_Filter]","Beller='" & [Naam] & "' AND Actie = 3");

MS access join two tables, get unique rows

This is a modification to a previous question original answer , I hope the proper thing to do is start a new thread.
I have a table called Parts, PartRefID is the PK
PartRefID PartDefID AssemblyID
1 2 c63df10b-8250-4aa5-9889-9e8046331dbf
11 1 db51f4a8-3ffa-41f7-81c1-a9accbbb299a
67 6 136fc5d8-7b65-41b5-bca3-7d4180a1e0ab
77 5 38fa8b7a-2945-4546-8eab-7865a1e515b2
133 2 c63df10b-8250-4aa5-9889-9e8046331dbf
134 6 136fc5d8-7b65-41b5-bca3-7d4180a1e0ab
I need to extract rows with a unique AssemblyID. This was answered by GMB with the following sql:
select *
from parts as p
where [PartRefID] = (
select max(p1.[PartRefID])
from parts as p1
where p1.[AssemblyID] = p.[AssemblyID] and p1.[PartDefID] = 2
)
which worked beautifully. However requirements have changed and I must ignore the PartDefID field and there could also be AssemblyID's which represent parts I do not want.
The AssemblyID's shown in the above table represent an electrical connector part.
Electrical connector parts will ALWAYS have a Partclass of 1 which is defined in another table called PartDefinitions shown here:
PartDefID PartClass PartNumber
1 1 MS27467T23F55P
2 1 330-00186-09
3 2 336-00024-00
4 2 336-00022-00
5 1 MS27468T23F55S
6 1 330-00184-09
with my limited sql knowledge I decided a join was necessary and came up with the following code:
SELECT Parts.*, PartDefinitions.PartClass
From PartDefinitions
INNER Join Parts
On PartDefinitions.PartDefID = Parts.PartDefID
Where (((PartDefinitions.PartClass) = 1))
this gets me close, it produces all the parts in the parts table which are connectors. However there are some duplicate AssemblyID's.
what I need is to produce the following:
PartRefID PartDefID AssemblyID
1 2 c63df10b-8250-4aa5-9889-9e8046331dbf
11 1 db51f4a8-3ffa-41f7-81c1-a9accbbb299a
67 6 136fc5d8-7b65-41b5-bca3-7d4180a1e0ab
77 5 38fa8b7a-2945-4546-8eab-7865a1e515b2
my apologies if I have not made a clear and concise question
thanks for any help
and thanks again GMB
If I understand correctly, you want to filter by the PartClassId in both the subquery and the outer query:
select p.*, pd.PartClass
From Parts as p inner join
PartDefinitions as pd
on pd.PartDefID = p.PartDefID
where pd.PartClassId = 1 and
p.pPartRefID = (select max(p2.pPartRefID)
from parts as p2 inner join
PartDefinitions as pd2
on pd2.PartDefID = pd.PartDefID
where p2.AssemblyID = p.AssemblyID and
p2.PartClassId = 1
)

How can I show combined "article" which has the same amount of "bids"?

I want to show the combinations of "offers" that have the same number of "bids". The Both "OID" of the combination and the number of "bids" should be output.
I know the logic I want to show which article has the same bids in combination of other article, but I don't know how I can write it down. Some code can help me to understand this.
More information about the structure of the tables "offer" and "bid". Also a "Expected result" which is shown the result
I really want to learn SQL.
Try running this..
SELECT temp1.OID as OID1,temp2.OID as OID2,temp1.count1 as numberOfBids
FROM
(SELECT t1.OID,COUNT(t1.BID) as count1
FROM bid t1 group by t1.OID) temp1
JOIN
(SELECT t2.OID,COUNT(t2.BID) as count2
FROM bid t2 group by t2.OID) temp2
ON temp1.count1= temp2.count2
AND temp1.OID <> temp2.OID
But it will give output as below table
OID1 OID2 numberOfBids
1 2 2
1 5 2
2 5 2
5 1 2
5 2 2

join in sql or ms-access?

There is a table like this in the format of SQL or ms-access.
Sample
ID ID2 name class example
1 10 John main
2 10
3 10
4 10 ~ is look at me.
5 20 Candice main
6 20
7 20 ~ is in Japan.
8 20 ~ is reading a book.
9 20
I need to replace "~" in example fields(A) with the value of name field that has the same ID2 as A and class = "main". How do I make a join syntax?
Result
ID ID2 name class example
1 10 John main
2 10
3 10
4 10 John is look at me.
5 20 Candice main
6 20
7 20 Candice is in Japan.
8 20 Candice is reading a book.
9 20
I think your table configuration is not correct.
The fact that you are using a ID field whose valor is repeated on the table points to a somewhat bad database design.
I think you'd probably get better results splitting your data between two tables, one with the examples and one with the "main" classes. Then you'll be able to join both tables through a simple join using ID2 field.
select m.[name] & replace(b.example, "~", "") as combined
from sample as m
inner join sample as b on m.id2 = b.id2
where m.[class] = "main"
and b.example not null
Although the data is structured terribly (for whatever reason), to answer your question, you can do it like this:
SELECT
T1.[ID],
T1.[ID2],
T1.[name],
T1.[class],
iif(not isnull(T1.[Example]) and not isnull(T2.[Name]), Replace(T1.[Example], "~", T2.[Name]), null) As [Example]
FROM
Data T1
LEFT JOIN Data T2 ON (T1.[ID2] = T2.[ID2] AND T2.[Class]="main")
This relies on the assumption that there is only one record with class=main for each unique value of ID2 (otherwise you will get repeats of rows).
Without the requirement of using a JOIN, an alternative is this:
SELECT
[ID],
[ID2],
[name],
[class],
(iif(not isnull([example]), Replace([example], "~", nz((select top 1 [name] from Data T2 where T2.ID2 = T1.ID2 and T2.[class]="main" order by T2.[ID2]),"")),null)) as [ExampleNew]
FROM Data T1

Why does this query return "incorrect" results?

I have 3 tables:
'CouponType' table:
AutoID Code Name
1 CouT001 SunCoupon
2 CouT002 GdFriCoupon
3 CouT003 1for1Coupon
'CouponIssued' table:
AutoID CouponNo CouponType_AutoID
1 Co001 1
2 Co002 1
3 Co003 1
4 Co004 2
5 Co005 2
6 Co006 2
'CouponUsed' table:
AutoID Coupon_AutoID
1 2
2 3
3 5
I am trying to join 3 tables together using this query below but apparently I am not getting right values for CouponIssued column:
select CouponType.AutoID, Code, Name, Count(CouponIssued.CouponType_AutoID), count(CouponUsed.Coupon_AutoID)
from (CouponType left join CouponIssued
on (CouponType.AutoID = CouponIssued.CouponType_AutoID))
left join CouponUsed
on (couponUsed.Coupon_AutoID = CouponIssued.AutoID)
group by CouponType.AutoID, code, name
order by code
The expected result should be like:
**Auto ID Code Name Issued used**
1 CouT001 SunCoupon 3 2
2 CouT002 GdFriCoupon 3 1
3 CouT003 1for1Coupon 0 0
Thanks!
SELECT t.AutoID
,t.Code
,t.Name
,count(i.CouponType_AutoID) AS issued
,count(u.Coupon_AutoID) AS used
FROM CouponType t
LEFT JOIN CouponIssued i ON i.CouponType_AutoID = t.AutoID
LEFT JOIN CouponUsed u ON u.Coupon_AutoID = i.AutoID
GROUP BY 1,2,3;
You might consider using less confusing names for your table columns. I have made very good experiences with using the same name for the same data across tables (as far as sensible).
In your example, AutoID is used for three different columns, two of which appear a second time in another table under a different name. This would still make sense if Coupon_AutoID was named CouponIssued_AutoID instead.
change count(Coupon.CouponType_AutoID) to count(CouponIssued.CouponType_AutoID) and count(Coupon.Coupon_AutoID) to count(CouponUsed.Coupon_AutoID)