divide data in sql to groups order by another column - sql

I have this set of data
shopId companyId date
1 1 25/8/2015
2 1 26/8/2015
3 1 22/8/2015
4 2 20/8/2015
5 2 27/8/2015
what i need is to get this result
shopId companyId date dense_rank
1 2 27/8/2015 1
2 2 20/8/2015 1
3 1 26/8/2015 2
4 1 25/8/2015 2
5 1 22/8/2015 2
how to get all groups ranked but order with date

SELECT *
, DENSE_RANK() OVER (ORDER BY companyId DESC, [Date] DESC) AS [DENSE_RANK]
FROM TableName

If you want the groups ordered by date, then you need two steps: first get the maximum date for each group. Then use dense_rank():
select shopid, companyid, date,
dense_rank() over (order by maxd desc) as dense_rank
from (select t.*, max(date) over (partition by companyid) as maxd
from table t
) t
Note: this assumes that your date is really stored as a date and not as a string. You will need additional transformations if the data is (improperly) stored as a string.

Related

Oracle SQL: receive ID of grouped foreign key with smallest Date

I have a table given.
I need the ID of each BID with the smallest MODIFIED date
ID
BID
MODIFIED
1
1
01.01.2020
2
1
01.07.2020
3
2
04.08.2020
4
2
04.06.2020
5
2
01.07.2020
6
2
01.10.2020
7
3
01.09.2020
Desired output:
ID
BID
MODIFIED
1
1
01.01.2020
4
2
04.06.2020
7
3
01.09.2020
so far, I can get a list of BIDs with the smallest MODIFIED date, but not the ID from it:
select BID, min(MODIFIED) from MY_TABLE group by BID
how can I receive the ID, however?
Oracle has a "first" aggregation function, which uses the keep syntax:
select BID, min(MODIFIED),
min(id) keep (dense_rank first over order by modified) as id
from MY_TABLE
group by BID;
A common alternative uses window functions:
select t.*
from (select t.*,
row_number() over (partition by bid order by modified asc) as seqnum
from my_table t
) t
where seqnum = 1;

Find gaps of a sequence in PostgreSQL tables

I have a table invoices with a field invoice_number. This is what happens when i execute select invoice_number from invoice
invoice_number
1
2
3
5
6
10
11
I want a SQL that gives me the following result:
gap_start
gap_end
1
3
5
6
10
11
demo:db<>fiddle
You can use row_number() window function to create a row count and use the difference to your actual values as group criterion:
SELECT
MIN(invoice) AS start,
MAX(invoice) AS end
FROM (
SELECT
*,
invoice - row_number() OVER (ORDER BY invoice) as group_id
FROM t
) s
GROUP BY group_id
ORDER BY start

Group by data based with same group occuring multiple times

Input data
id group
1 a
1 a
1 b
1 b
1 a
1 a
1 a
expected result
id group row_number
1 a 1
1 a 1
1 b 2
1 b 2
1 a 4
1 a 4
1 a 4
I require the rwo_number based on the above result. If the same group occurring the second time generates different row_number for that? I have one more column sequence of date top to end.
This is an example of a gaps-and-islands problem. Solving it, though, requires that the data be ordered -- and SQL tables represent unordered sets.
Let me assume you have such a column. Then the difference of row numbers can be used:
select t.*,
dense_rank() over (partition by id order by grp, (seqnum - seqnum_g)) as grouping
from (select t.*,
row_number() over (partition by id order by ?) as seqnum,
row_number() over (partition by id, grp order by ?) as seqnum_g
from t
) t;
This does not produce the values that you specifically request, but it does identify each group.

How to select top 2 values for each id

I have a table with values
id sales date
1 5 "2015-01-04"
1 3 "2015-01-03"
1 1 "2015-01-01"
1 1 "2015-01-01"
2 7 "2015-01-05"
2 6 "2015-01-04"
2 4 "2015-01-03"
3 11 "2015-01-08"
3 10 "2015-01-07"
3 9 "2015-01-06"
3 8 "2015-01-05"
I want to select top two values of each id as shown in desired output.
Desired output:
id sales date
1 5 "2015-01-04"
1 3 "2015-01-03"
2 7 "2015-01-05"
2 6 "2015-01-04"
3 11 "2015-01-08"
3 10 "2015-01-07"
My attempt:
can someone help me with this. Thank you in advance!
select transactions.salesperson_id, transactions.id, transactions.date
from transactions
ORDER BY transactions.salesperson_id ASC, transactions.date DESC;
This can be done using window functions:
select id, sales, "date"
from (
select id, sales, "date",
dense_rank() over (partition by id order by "date" desc) as rnk
from transactions
) t
where rnk <= 2;
If there are multiple rows on the same date this might return more than two rows for the same ID. If you don't want that, use row_number() instead of dense_rank()
row_number() will get what you want.
select * from
(select row_number() over (partition by id order by date) as rn, sales, date from transactions) t1
where t1.rn <= 2

select query based on priority

I have table
Id createdonutc
1 2014-05-29 10:14:00.240
2 2014-05-29 10:16:58.587
3 2014-06-01 11:32:54.140
4 2014-05-29 10:48:40.427
6 2014-06-01 2:1:54.140
I want to get the data with orderby date only(no time) desc
Id createdonutc rank
3 2014-06-01 11:32:54.140 1
6 2014-06-01 2:1:54.140 1
1 2014-05-29 10:14:00.240 2
2 2014-05-29 10:16:58.587 2
4 2014-05-29 10:48:40.427 2
i tried:
SELECT
id,
P.createdonutc,
ROW_NUMBER() OVER (PARTITION BY cast(p.[CreatedOnUtc] AS DATE) ORDER BY cast(p.[CreatedOnUtc] AS DATE) desc) as num
FROM
news p
ORDER BY num
it shows no change on the result.How can i get it to work ?
Please try using DENSE_RANK():
SELECT
id,
P.createdonutc,
Dense_Rank() OVER (ORDER BY cast(p.[CreatedOnUtc] AS DATE) desc) as num
FROM
news p
ORDER BY num
Row_Number generate a different number for every row, even when the values are equal, to get what you want you need to use DENSE_RANK
SELECT id, createdonutc
, dense_rank() OVER (order by cast(createdonutc as date) DESC)
FROM News
SQLFiddle demo