Selecting first row from a group after order - hive

Here is what my table looks like:
appl_db_srvr_xref_id secrty_ctl_id assmt_dt cmdb_id secrty_ctl_elemnt_impmtn_cd
180 43 1/1/2018 227 N
180 43 9/31/2018 227 Y
179 28 1/1/2018 710 N
179 29 2/2/2018 710 N
179 43 3/3/2018 710 N
What I need is to group by (appl_db_srvr_xref_id, secrty_ctl_id, and cmdb_id) sort by date, and return the most current row. So in this instance I would like to return:
180 43 227 Y
179 28 710 N
179 29 710 N
179 43 710 N
what I am trying is:
SELECT secrty_ctl_id,
appl_db_srvr_xref_id,
cmdb_id,
assmt_dt
FROM tablename
GROUP BY
secrty_ctl_id,
appl_db_srvr_xref_id,
cmdb_id
ORDER BY assmt_dt desc

Use row_number() analytic function:
select
secrty_ctl_id,
appl_db_srvr_xref_id,
cmdb_id,
assmt_dt
from
(
SELECT secrty_ctl_id,
appl_db_srvr_xref_id,
cmdb_id,
assmt_dt,
row_number() over (partition by appl_db_srvr_xref_id, secrty_ctl_id, cmdb_id order by assmt_dt desc) rn
FROM tablename
)s
where rn=1;

Related

Summing column that is grouped - SQL

I have a query:
SELECT
date,
COUNT(o.row_number)FILTER (WHERE o.row_number > 1 AND date_ddr IS NOT NULL AND telephone_number <> 'Anonymous' ) repeat_calls_24h
(
SELECT
telephone_number,
date_ddr,
ROW_NUMBER() OVER(PARTITION BY ddr.telephone_number ORDER BY ddr.date) row_number,
FROM
table_a
)o
GROUP BY 1
Generating the following table:
date
Repeat calls_24h
17/09/2022
182
18/09/2022
381
19/09/2022
81
20/09/2022
24
21/09/2022
91
22/09/2022
110
23/09/2022
231
What can I add to my query to provide a sum of the previous three days as below?:
date
Repeat calls_24h
Repeat Calls 3d
17/09/2022
182
18/09/2022
381
19/09/2022
81
644
20/09/2022
24
486
21/09/2022
91
196
22/09/2022
110
225
23/09/2022
231
432
Thanks
We can do it using lag.
select "date"
,"Repeat calls_24h"
,"Repeat calls_24h" + lag("Repeat calls_24h") over(order by "date") + lag("Repeat calls_24h", 2) over(order by "date") as "Repeat Calls 3d"
from t
date
Repeat calls_24h
Repeat Calls 3d
2022-09-17
182
null
2022-09-18
381
null
2022-09-19
81
644
2022-09-20
24
486
2022-09-21
91
196
2022-09-22
110
225
2022-09-23
231
432
Fiddle

Create calculated field from MIN() and MAX() values of another column, grouped by unique ID

I have a table that looks like this, containing information about an object's position and the length of time it existed for (age):
Date ID Age x y
2021-03-25 20 1 531 295
2021-03-25 20 2 478 272
2021-03-25 20 3 421 272
2021-03-26 20 1 478 286
2021-03-26 21 1 903 342
And I am trying to select the x position of a certain ID, when the age is at its minimum value for that ID (column named xStart), and when it is at its maximum value (column named xFin). IDs represent a different object on each day, so ID 20 on the 25th will not be the same object as ID 20 on the 26th.
I would like the resulting table to look something like this:
Date ID Age x y xStart xEnd
2021-03-25 20 1 531 295 531 421
2021-03-25 20 2 478 272 531 421
2021-03-25 20 3 421 272 531 421
2021-03-26 20 1 478 286 478 some number
2021-03-26 21 1 903 342 908 some other number
And that table could be grouped for each ID:
Date ID MAX(Age) xStart xEnd
2021-03-25 20 3 531 421
2021-03-26 20 1 478 some number
2021-03-26 21 1 908 some other number
You can use window functions, if I understand:
select distinct date, id,
max(age) over (partition by date, id),
first_value(x) over (partition by date, id order by age) as xstart,
first_value(x) over (partition by date, id order by age desc) as xend
from t;

SQL Server Obtain Pairs of records

I am trying to obtain "pairs" of records and I just cant figure out.
Here is what I have:
Id TruckId LocationId MaterialMode
145223 1198 19 43
145224 1199 19 43
145225 1200 19 43
145226 1198 20 43
145227 1199 20 43
145228 1200 20 43
145229 1199 21 46
145230 1198 21 46
145231 1200 21 46
145232 1198 22 46
145233 1199 22 46
145234 1200 22 46
145235 1198 19 43
145236 1199 19 43
145237 1200 19 43
145238 1198 20 43
145239 1199 20 43
145240 1200 20 43
145241 1199 21 46
145242 1198 21 46
145243 1200 21 46
145244 1198 22 46
145245 1199 22 46
145246 1200 22 46
I need to get the following:
Id A Id B
145223 145226
145224 145227
145225 145228
145229 145233
145230 145232
145231 145234
145235 145238
145236 145239
145237 145240
145241 145245
145242 145244
145243 145246
Basically matching a TruckId between 2 locations under the same material mode
I have tried:
SELECT
Id AS IdA,
Lead(Id, 1, NULL) OVER(PARTITION BY TruckId, MaterialMode ORDER BY Date) AS IdB
FROM T
This produces:
Id A Id B
145223 145226
145224 145227
145225 145228
*145226 145235
*145227 145236
*145228 145237
145229 145233
145230 145232
145231 145234
*145232 145242
*145233 145241
*145234 145243
145235 145238
145236 145239
145237 145240
145241 145245
145242 145244
145243 145246
Records with the * I don't want them. If a pair is matched then that record should not be part of "another match"
I believe I understand your problem and below is a solution.
Explanation: I sorted the data rows into start and end points sets like in gap and islands problems and then joined a start id with end id for same material mode and truck.
; with separationSet as
(
select
*,
dense_rank()
over(
partition by materialmode,truckid
order by locationid asc
) as r
from T
)
, scoredSet as
(
select
*,
row_number()
over(
partition by materialmode,truckid,r
order by id
) as r2
from separationSet
)
, startToEndPairs as
(
select
S.id as StartId,
E.id as EndId
from scoredSet S
join scoredSet E
on S.r=1 and E.r=2
and S.r2=E.r2
and S.TruckId=E.TruckId
and S.materialmode=E.materialmode
)
select
*
from starttoEndPairs
order by StartId asc
See working demo

how to give different row id to sub group in in a group in sql query?

i have bunch of discount scheme for my item table , and for each item i have different discount scheme. now i want to give row id to that item but it should be start from zer0(0) for each item group, and when it got different DiscountId then it should be change, my table is in below image..
now for an example, for ItemCode 429 there are 7 same discount with DiscountId 427 so for this all i want row Id 0(zero) but when change DiscountId, it means for Same ItemCode and 428 DiscountId, then i want another RowId with increment. and when ItemCode change then rowId should be start from Zero(0).
can anyone help me please??
my current query is simpaly "select * from ItemDiscount_md".
Maybe something like this:
Test data:
DECLARE #tbl TABLE(ITEMCode INT,DiscountId INT)
INSERT INTO #tbl
VALUES
(73,419),(73,419),(73,420),(73,420),(73,420),
(429,427),(429,427),(429,427),(429,427),(429,427),
(429,427),(429,427),(429,427),(429,428),(429,428)
Query:
;WITH CTE
AS
(
SELECT
DENSE_RANK() OVER(PARTITION BY tbl.ITEMCode
ORDER BY DiscountId) AS Rownbr,
tbl.*
FROM
#tbl AS tbl
)
SELECT
CTE.Rownbr-1 AS RowNbr,
CTE.DiscountId,
CTE.ITEMCode
FROM
CTE
Of course you can simplify the query by writing this:
SELECT
(DENSE_RANK() OVER(PARTITION BY tbl.ITEMCode
ORDER BY DiscountId))-1 AS Rownbr,
tbl.*
FROM
#tbl AS tbl
I just thought it was nicer and more readable with a CTE function
References:
DENSE_RANK
OVER Clause
Using Common Table Expressions
ROW_NUMBER
EDIT
To answer the comment. No ROW_NUMBER will not return the same counter. This is the output with DENSE_RANK:
0 419 73
0 419 73
1 420 73
1 420 73
1 420 73
0 427 429
0 427 429
0 427 429
0 427 429
0 427 429
0 427 429
0 427 429
0 427 429
1 428 429
1 428 429
And this is with ROW_NUMBER:
0 419 73
1 419 73
2 420 73
3 420 73
4 420 73
0 427 429
1 427 429
2 427 429
3 427 429
4 427 429
5 427 429
6 427 429
7 427 429
8 428 429
9 428 429
As you see ROW_NUMBER() recounts the group when the DENSE_RANK ranks the group
Just more simplified Arion's Answer
DECLARE #tbl TABLE(ITEMCode INT,DiscountId INT)
INSERT INTO #tbl
VALUES
(73,419),
(73,419),
(73,420),
(73,420),
(73,420),
(429,427),
(429,427),
(429,427),
(429,427),
(429,427),
(429,427),
(429,427),
(429,427),
(429,428),
(429,428)
;
SELECT
(DENSE_RANK() OVER(PARTITION BY ITEMCode ORDER BY DiscountId) -1) AS Rownbr,
DiscountId,
ITEMCode
FROM
#tbl
if you got data like this: (from the image) #temp table
itemcode DiscountId DayId
----------- ----------- -----------
102 416 2
102 416 3
102 416 4
79 419 3
79 419 1
79 420 2
79 420 1
use row_number() to get below result
itemcode DiscountId DayId rowid
----------- ----------- ----------- --------------------
102 416 2 1
102 416 3 2
102 416 4 3
79 419 3 1
79 419 1 2
79 420 2 1
79 420 1 2
SQL example:
select itemcode, DiscountId, DayId
, ROW_NUMBER() over (partition by Discountid order by discountid) as 'rowid'
from #temp

How to get min date of every month for six months?

I have data like this.
Process_date SEQ_No
------------- ---------
16-MAR-13 733
09-MAR-13 732
02-MAR-13 731
24-FEB-13 730
16-FEB-13 728
09-FEB-13 727
02-FEB-13 726
26-JAN-13 725
21-JAN-13 724
12-JAN-13 723
05-JAN-13 722
29-DEC-12 721
24-DEC-12 720
15-DEC-12 719
08-DEC-12 718
03-DEC-12 717
22-NOV-12 716
17-NOV-12 715
10-NOV-12 714
03-NOV-12 713
29-OCT-12 712
23-OCT-12 711
13-OCT-12 710
05-OCT-12 709
28-SEP-12 708
22-SEP-12 707
15-SEP-12 706
08-SEP-12 705
01-SEP-12 704
Every month admin will refresh actual data table and automatically this above table will update with unique seq_no and process_date.
I need to extarct min date of everymonth(First refresh of last 6 months - excluding currrent month) and also seq_no related to that month so using joins(using seq_no - that is available in main table) i can combine actual data.
I need result like:
02-MAR-13 731 ( I don't need MAR as it should not take current month data)
so i need final result like below:
02-FEB-13 726
05-JAN-13 722
08-DEC-12 718
03-NOV-12 713
05-OCT-12 709
01-SEP-12 704
--sorry for asking direct quetion like this. I am not sure how to do that. thats the reason i have not prepared/posted any query.
select Process_date, SEQ_No
from (select Process_date, SEQ_No,
row_number() over (partition by trunc(process_date, 'mm') order by process_date) rn
from yourtab
where Process_date < trunc(sysdate, 'mm'))
where rn = 1;
will do that
fiddle example: http://sqlfiddle.com/#!4/a5452/1
I didn't understood how seq_no is in another table...
But using the input data:
select
min(process_date),
min(seq_no) keep (dense_rank first order by process_date)
from
your_table
where
process_date between add_months(trunc(sysdate,'MM'),-7)
and last_day(add_months(sysdate, -1))
group by
trunc(process_date,'MM');
Try:
SELECT seq_no,process_date FROM my_table
WHERE process_date IN (SELECT min(process_date)
FROM my_table
GROUP BY TRUNC(process_date,'MM'))