Access SQL - Select only the last sequence - sql

I have a table with an ID and multiple informative columns. Sometimes however, I can have multiple data for an ID, so I added a column called "Sequence". Here is a shortened example:
ID Sequence Name Tel Date Amount
124 1 Bob 873-4356 2001-02-03 10
124 2 Bob 873-4356 2002-03-12 7
124 3 Bob 873-4351 2006-07-08 24
125 1 John 983-4568 2007-02-01 3
125 2 John 983-4568 2008-02-08 13
126 1 Eric 345-9845 2010-01-01 18
So, I would like to obtain only these lines:
124 3 Bob 873-4351 2006-07-08 24
125 2 John 983-4568 2008-02-08 13
126 1 Eric 345-9845 2010-01-01 18
Anyone could give me a hand on how I could build a SQL query to do this ?
Thanks !

You can calculate the maximum sequence using group by. Then you can use join to get only the maximum in the original data.
Assuming your table is called t:
select t.*
from t join
(select id, MAX(sequence) as maxs
from t
group by id
) tmax
on t.id = tmax.id and
t.sequence = tmax.maxs

Related

Using a top x count query as a where clause to show all qualifying records

I have a count of a top 2
My table has this data
Name Age price visited size
Jon 34 53 2018-01-01 9
Don 22 70 2018-03-01 15
Pete 76 12 2018-11-09 7
Jon 34 55 2018-09-13 9
Paul 90 64 2018-07-08 6
Pete 76 31 2018-03-25 7
Jon 75 34 2018-06-06 8
select top 2
name,
count(name) as cnt
from
tbl1
group by name
order by cnt desc
Which returns my top 2 names
Jon 3
Pete 2
This name will change dynamically as the query is run depending on who has made the most visits in total (this is very simplified the actual table has 1000's of entries).
What I would like to do is then use the result of that query to get the following all of which needs to be in a single query;
Name Age price visited size
Jon 34 53 2018-01-01 9
Jon 34 55 2018-09-13 9
Jon 75 34 2018-06-06 8
Pete 76 12 2018-11-09 7
Pete 76 31 2018-03-25 7
In summary, count who has visited the most and then display all the records under those names.
Thanks in advance
Here's one option using in:
select *
from yourtable
where name in (
select top 2 name
from yourtable
group by name
order by count(*) desc
)
order by name
Online Demo

count of a column in the result set on which distinct is already applied

Consider the table Property.
KeyIdNum|Property|IdNum
1 12 1234
1 12 1234
1 44 1234
1 12 1234
1 56 1234
2 12 4567
3 12 6789
3 56 6789
3 12 6789
4 44 3434
5 12 4444
6 44 9999
6 44 9999
It contains property num associated with each id num.But it contains duplicates.
I applied distinct to avoid duplicates.
select distinct KeyIdNum,Property,IdNum from Property.
So i got the result as :
KeyIdNum |Property |IdNum
1 12 1234
1 44 1234
1 56 1234
2 12 4567
3 12 6789
3 56 6789
4 44 3434
5 12 4444
6 44 9999
But now I want to `select( after applying distinct) ,the KeyIdNum (or IdNum) which are coming more than one time in the distinct result set shown above.
Please help me on this.I am not able to find a way to get the count of a column in the distinct result set using a single query.
Below query will result of KeyidNum , its number of row count.
select KeyIdNum,count(KeyIdNum)
From (
select distinct KeyIdNum,Property,IdNum from Property )
group by KeyIdNum
select KeyIdNum,count(KeyIdNum) as count
From (
select distinct KeyIdNum,Property,IdNum from Table19 )A
group by KeyIdNum
output
KeyIdNum count
1 3
2 1
3 2
4 1
5 1
6 1
This answer uses t-sql:
SELECT x
FROM ( SELECT * ,
rn = rownumber() OVER ( PARTITION BY keyidnum, idnum
ORDER BY keyidnum, idnum )
FROM tblProperty
) x
WHERE rn > 1

Using sequences to create group ID

I'm attempting to create group_ids based on a set of item_ids. The only indication that the item_ids are part of a single group is the fact that item_ids are sequential. For example, based on the first two columns below, the output I want is the third:
item item_id group_id
ABC 282 2
ABC 283 2
ABC 284 2
ABC 285 2
ABC 051 3
ABC 052 3
ABC 189 4
ABC 231 5
ABC 232 5
ABC 233 5
ABC 234 5
ABC 247 6
ABC 248 6
ABC 249 6
ABC 250 6
ABC 091 7
ABC 092 7
The group_id doesn't necessarily have to be sequential itself, it only has to be unique. I attempted this with the following code:
create sequence seq
start with 1
minvalue 1
increment by 1
cache 20;
select seq.nextval from dual; --to initialize the sequence
select
item,
item_id,
case when diff = 1 then seq.currval else seq.nextval end group_id
from
(
select
item,
item_id,
(id - lag(id, 1, 0) over (order by 1) diff
from
(
select
item,
item_id
from
table
)
);
But get the following output:
item item_id group_id
ABC 282 2
ABC 283 3
ABC 284 4
ABC 285 5
ABC 051 6
ABC 052 7
ABC 189 8
ABC 231 9
ABC 232 10
ABC 233 11
ABC 234 12
ABC 247 13
ABC 248 14
ABC 249 15
ABC 250 16
ABC 091 17
ABC 092 18
When looking for the cause of the problem, I found an excellent explanation by user ShannonSeverance that details why my solution won't work. However, it didn't provide any suggestions on how to move forward.
Does anyone have any ideas?
You have a problem, because SQL tables are inherently unordered. The following "should" logically work, although it won't in practice:
select ii.*, (item_id - rownum) as grp_id
from item_ids ii;
A sequence of item_ids in order minus the row number is constant. You can use that for a group, at least for a given item. To handle multiple items, concatenate the values together:
select ii.*, item||'-'||(item_id - rownum) as grp_id
from item_ids ii;
To really make this work, you need to add an order by -- this guarantees the ordering of the results from the select. This might work, assuming that there are "holes" between the groups:
select ii.*, item||'-'||(item_id - rownum) as grp_id
from item_ids ii
order by item, item_id;
Otherwise, you need some other column to determine the proper ordering for the items.

How to create an internal numbering of occurrences with SQL

How can I create a new column (inCount) with numbering of occurrences in a specific column?
Here is an example:
id name inCount
1 Orly 1
2 Ernest 1
3 Rachel 1
4 Don 1
5 Don 2
6 Ernest 2
7 Angela 1
8 Ernest 3
9 David 1
10 Rachel 2
11 Sully 1
12 Sully 2
13 Rachel 3
14 David 2
15 David 3
16 Kevin 1
17 Kevin 2
18 Orly 2
19 Angela 2
20 Sully 3
21 Kevin 3
22 Don 3
23 Orly 3
24 Angela 3
Don from id 5 is numbered 2 because Don appears in id 4 too.
Don from id 22 is numbered 3 due to the above preceding occurrences.
I use MS SQL SERVER 2008 R2 Express edition.
Thanks.
You could use partition by, like:
select row_number() over (partition by name order by id) as inCount
, *
from YourTable
order by
id
This should work
SELECT id, Name, ROW_NUMBER() OVER(PARTITION BY Name ORDER BY id)
FROM table
ORDER BY id
EDIT: Added order by clause on the select in order to show results in same order indicated by OP. The ORDER BY in the ROW_NUMBER did not change the outcome, but I changed to id as it will keep the row_number correct for the sample data.

Combine rows adding specific columns

I have a table similar to the following:
employee_id | totalWorkHours | projectID
1 20 123
1 20 321
2 15 222
2 25 333
3 10 434
3 12 343
Is it possible to combine rows based on employee_id, but add totalWorkHours into an actual total for an employee and present in a result set without modifying the table?
So the results would be something like:
employee_id | actualTotalWorkHours
1 40
2 40
3 22
Or is this something better done with the raw result set?
Any help is much appreciated.
Select employee_id, Sum(totalWorkHours) As actualWorkHours
From YourTableName
Group By employee_id
Order By employee_id