Microsoft Access finding second, third, Nth element in a group - database

I have a table: worker_id, company_id
worker_id is primary key
worker_id | company_id
----------------------
1 | 1
2 | 1
3 | 2
4 | 3
5 | 3
6 | 1
I know how to find the first worker_id in each company_id using Min()
SELECT Min([workers per company].worker_id) AS MinOfworker_id, [workers per company].company_id
FROM [workers per company]
GROUP BY [workers per company].company_id;
Resulting in:
worker_id | company_id
----------------------
1 | 1
3 | 2
4 | 3
I know how to find the last worker_id in each company_id using Max()
SELECT Max([workers per company].worker_id) AS MaxOfworker_id, [workers per company].company_id
FROM [workers per company]
GROUP BY [workers per company].company_id;
Resulting in:
worker_id | company_id
----------------------
6 | 1
3 | 2
5 | 3
Now I want to get the second (or third, Nth) worker_id per company_id resulting in:
worker_id | company_id
----------------------
2 | 1
5 | 3
There is a way to do this?
EDIT:
In kdb+ I can use:
select w:worker_id[1] by company_id from workers_per_company
to get the 2nd worker_id
resulting in:
company_id| w
-------------
1 | 2
2 |
3 | 5
Is there something similar in MS Access?

You are trying to do something in SQL that SQL was not meant for. Instead, consider writing a VBA procedure to iterate over a recordset sorted by company.

Related

Displaying data in a different manner

So I have a table that binds ProductId and GroupId. The product can be assigned to all of 5 groups (1-5).
If the product doesn't exist in the table, it's not assigned to any of the group
ProductId | GroupId
-------------------
100 | 1
100 | 2
200 | 1
200 | 2
200 | 3
200 | 4
200 | 5
Taking a look at this table, we know that Product that goes by id 100 is assigned to 2 groups (1,2) and the product of id 200 is assigned to 5 groups (1-5).
I'm trying to write a query that will display each product in separate row, together with columns for all of the 5 groups and a bit value that contains information if the product belongs to the group or not (0,1). A visualization of the result I need:
ProductId | IsGroup1 | IsGroup2 | IsGroup3 | IsGroup4 | IsGroup5
-----------------------------------------------------------------
100 | 1 | 1 | 0 | 0 | 0 -- this belongs to groups 1, 2
200 | 1 | 1 | 1 | 1 | 1 -- this belongs to all of the groups
I know I could probably solve it using a self join 5 times on each distinct product, but I'm wondering if there's a more elegant way of solving it?
Any tips will be strongly appreciated
You could use a pivot. Since you only have 5 groups you don't need a dynamic pivot.
DB FIDDLE
select
ProductId
,IsGroup1 = iif([1] is null,0,1)
,IsGroup2 = iif([2] is null,0,1)
,IsGroup3 = iif([3] is null,0,1)
,IsGroup4 = iif([4] is null,0,1)
,IsGroup5 = iif([5] is null,0,1)
from
(select ProductID, GroupId from mytable) x
pivot
(max(GroupId) for GroupId in ([1],[2],[3],[4],[5])) p

SQLite3 count how many counts?

I'm learning SQLite3 and having trouble with this particular output.
Let's say I have a column like:
user0
user1
user1
user2
user2
user3
user3
user3
user4
user4
user4
user4
I would like to count how many times a user appears in the column, and having an output like:
1 | 1
2 | 2
1 | 3
1 | 4
Meaning: There is 1 user appearing 1 time, 2 users appearing 2 times, 1 user appearing 3 times, 1 user appearing 4 times.
I don't need to know anything else, only how many users are with how many accounts.
You group by once to get the counters of the 1st column you need and then again on this result:
select count(*) total, counter
from (
select count(*) counter
from tablename
group by col
)
group by counter
See the demo
Results:
| total | counter |
| ----- | ------- |
| 1 | 1 |
| 2 | 2 |
| 1 | 3 |
| 1 | 4 |
Here is a small example using GROUP BY and the COUNT()-function.
Im using MSSQL, but it should be nearly the same in SQLITE3.
This is the table Im using:
select count([name]), [name] from Test
group by [name]
This is the result:

oracle database, Omitting records from a table which are subset of records in same table based on two columns

I have some customers which are clustered into groups by cluster_id and the amount of data is huge (So performance is a matter here). The simplest form of what I have is the following table:
cust_id | cluster_Id
---------- | -----------
1 | 1
2 | 1
3 | 1
2 | 2
1 | 2
2 | 3
4 | 3
1 | 4
I want those clusters with greatest number of customers such that no costumer be removed. In other words, I want to delete records of a cluster that is subset of another cluster.
In above example, the output table should look like this:
cust_id cluster_Id
-------- | ----------
1 | 1
2 | 1
3 | 1
2 | 3
4 | 3

Sql Total Sum using no of row counts in a table

i am trying to find the total marks for each student based on StudentId and MarksTypeId row count.
i have 3 tables
MarksType
----------------------------------
MarksTypeId | MarkType | Marks
----------------------------------
1 | Writing | 10
2 | Drawing | 30
3 | Singing | 20
----------------------------------
Students
--------------------------------
StudentId | Name | Address
--------------------------------
1 | John | USA
2 | Raja | India
3 | Paul | AUS
--------------------------------
MarksDetails -- Has two foreign keys
-------------------------------------------------------
MarksDetailsId | MarksTypeId | StudentId | Date
-------------------------------------------------------
1 | 3 | 1 | 18 jan
2 | 3 | 1 | 18 jan
3 | 1 | 3 | 19 jan
-------------------------------------------------------
This is my Desired Result :
------------------------------------
StudentId | Name | Total Marks
------------------------------------
1 | John | 40
2 | Raja | 0
3 | Paul | 10
------------------------------------
i mean if John sang two times a day, so using StudentId and MarksTypeId, i need his total Marks as result.
so far i did the following:
select Sum(MarksType.Marks) from MarksType inner join MarksDetails on MarksType.MarksTypeId=1
but the sum returns wrong total,
UPDATED OTHER ATTEMPTS:
this results total row count for each studentid
select MarksDetails.StudentId , COUNT(MarksDetails.StudentId ) as count from MarksDetails
group by MarksDetails.StudentId
this results Marks, with studentid and markstypeid
select MarksType.Marks, MarksType.MarksTypeId , MarksDetails.StudentId from MarksType inner join MarksDetails on MarksType.MarksTypeId = MarksDetails.StudentId
may i know what i am doing wrong.
Any help would be Great.
finally with kind guidance from sql developers and after making some research, here is the query with desired result, maybe useful for someone, enjoy !
SELECT Student.StudentId, Student.Name, sum(MarksType.Marks) as TotalMarks
FROM
MarksType
INNER JOIN
MarksDetails on MarksType.MarksTypeId = MarksDetails.MarksTypeId
INNER JOIN
Student on Student.StudentId = MarksDetails.StudentId
group by Student.Name,Student.StudentId

SQL Query to get data based on multiple filters

I have following Product table and ProductTag tables -
ID | Product
--------------
1 | Product_A
2 | Product_B
3 | Product_C
TagID | ProductID
----------------------
1 | 2
1 | 3
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
Now I need a SQL query that return all products list which are having both Tag 1 and 2. Result should be as given below -
ProductID | Product
------------------------
2 | Product_B
3 | Product_C
Please suggest how can i write a MS SQL query for this.
SELECT p.ID, p.Product
FROM Product p
INNER JOIN ProductTag pt
ON p.ID = pt.ProductID
WHERE pt.TagID IN (1, 2) -- <== Tags you want to find
GROUP BY p.ID, o.Product
HAVING COUNT(*) = 2 -- <== tag count on WHERE clause
however, if TagID is not unique on every Product, you need to count only the distinct product.
HAVING COUNT(DISTINCT pt.TagID) = 2
More on: SQL of Relational Division

Resources