Is there an SQL query that will count the number of occurrences of an event WITHOUT grouping the data by the event being counted? - sql

Note that I'm doing this in MS Access, so a solution using basic SQL operators would be appreciated.
Suppose you have a table where each row represents a coin flip in a series of coin flips.
Disclaimer: I'm using coin flips as an analogy so I don't have to explain my actual data set.
SELECT * FROM CoinFlips;
Id Flip Time
-------------------
1 Heads 1
2 Tails 2
3 Heads 3
4 Heads 4
5 Heads 5
6 Tails 6
How would you write a query that returns all of the rows above with an additional column that counts the number of 'head' flips that occurred up to that row's occurrence. In other words, this is what I want the result to look like:
Desired Output
Id Flip Time NumHeads
--------------------------------
1 Heads 1 1
2 Tails 2 1
3 Heads 3 2
4 Heads 4 3
5 Heads 5 4
6 Tails 6 4

To do this in MS Access, you need a correlated subquery or join/aggregation. Other databases have direct support for this functionality, but not MS Access.
select cf.*,
(select count(*)
from CoinFlips as cf2
where cf2.flip = 'Heads' and cf2.id <= cf.id
) as NumHeads
from CoinFlips as cf;

Well here is a solution
SELECT coinFlips.ID
,coinFlips.Flip
,coinFlips.TIME
,DCount("Flip", "coinFlips", "ID <=" & [Time] & "AND Flip ='Heads'") AS CountHeads
,DCount("Flip", "coinFlips", "ID <=" & [Time] & "AND Flip ='" & [Flip] & "'") AS CountEachOccurence
FROM coinFlips;

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");

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

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:

Google sheets queries with IF statments

I am trying to write this query for a while and have tried a few sites but not explain really how to use the IF statement.
So I have data in columns that are people scores for films
Jim
Jack
Fred
Film 1
6
6
2
Film 2
7
8
5
Film 3
3
5
8
...
for example and i want a query that when i select a cell with a name in it it will return the scores for that person (make top ten and scores by film genera / person etc.)
So I have this query I know the syntax is not correct I have tried many ways and cant get it to work. (E18 is the cell I with a pick list of the names)
=Query(Sheet1!A4:D,"select A & IF(E18=”Jim”, select B order by B desc Limit 10"")")
What I want to do is when I select a name then it returns the top 10 films for that user + the scores
Any help greatly received.
Thankyou
aaron
Let assume you will select actor name in F1 cell (as per my attached screenshot). They try below QUERY() formula.
=QUERY(A2:D4,"select A, " & CHAR(MATCH(F1,A1:D1,0)+64) & " order by " & CHAR(MATCH(F1,A1:D1,0)+64) & " desc limit 10")

How to calculate a progressive sum within an Access query

I have a query, let's call it qry_01, that produces a set of data similar to this:
ID N CN Sum
1 4 0 0
2 3 3 3
5 4 4 7
8 3 3 10
The values shown in this query actually come from a chain of queries and from a bunch of different tables.
The corrected value CN is calculated within the query, and counts N if the ID is not 1, and 0 if it is 1.
The Sum is the value I want to calculate by progressively summing up the CN values.
I tried to use DSUM, but I came out with nothing.
Can anyone please help me?
You could use a correlated subquery in the following way:
select t.id, t.n, t.cn, (select sum(u.cn) from qry_01 u where u.id <= t.id) as [sum]
from qry_01 t

T-SQL 2008 INSERT dummy row WHEN condition is met

**Schema & Dataset**
id version payment name
1 1 10 Rich
2 1 0 David
3 1 10 Marc
4 1 10 Jess
5 1 0 Steff
1 2 10 Rich
2 2 0 David
3 2 10 Marc
4 2 10 Jess
5 2 0 Steff
2 3 0 David
3 3 10 Marc
4 3 10 Jess
http://sqlfiddle.com/#!3/1c457/18 - Contains my schema and the dataset I'm working with.
Background
The data above is the final set after a stored proc has done it's processing so everything above is in one table and unfortunately I can't change it.
I need to identify in the dataset where a person has been deleted with a payment total greater than 0 in previous versions and insert a dummy row with a payment of 0. So in the above example, Rich has been deleted in version 3 with a payment total of 10 on previous versions. I need to first identify where this has happened in all instances and insert a dummy row with a 0 payment for that version. Steff has also been deleted on version 3 but she hasn't had a payment over 0 on previous versions so a dummy row is not needed for her.
Tried so far -
So I looked at pinal dave's example here and I can look back to the previous row which is great so it's a step in the right direction. I'm not sure however of how to go about achieving the above requirement. I've been toying with the idea of a case statement but I'm not certain that would be the best way to go about it. I'm really struggling with this one and would appreciate some advice on how to tackle it.
You can do this by generating all possible combinations of names and versions. Then filter out the ones you don't want according to the pay conditions:
select n.name, v.version, coalesce(de.payment, 0) as payment
from (select name, max(payment) as maxpay from dataextract group by name) n cross join
(select distinct version from dataextract) v left outer join
dataextract de
on de.name = n.name and de.version = v.version
where de.name is not null or n.maxpay > 0;
Here is a SQL Fiddle.