Finding Max Revision - sql-server-2008

I have a table similar to the below:
REQ PO LINE COST REV
101630 P101630 1 26.48 0
101630 P101630 2 26.82 0
101630 P101630 3 17.83 0
101630 P101630 1 26.48 1
101630 P101630 2 110.00 1
101630 P101630 3 17.83 1
101630 P101630 1 52.96 2
101630 P101630 2 110.00 2
101630 P101630 3 35.66 2
How would I find the result I want would be something like this:
REQ PO LINE COST REV
101630 P101630 1 52.96 2
101630 P101630 2 110.00 2
101630 P101630 3 35.66 2
I tried using this but it didn't return correct results
select req, po, line, cost, max(rev)
from table
where po= 'P101630'
group by req, po, line, cost

I would use (if you want last revision for each single REQ, PO, LINE):
SELECT REQ, PO, LINE, COST FROM (
SELECT REQ, PO, LINE, COST, ROW_NUMBER() OVER (PARTITION REQ, PO, LINE BY ORDER BY REV DESC) AS RN
FROM TABLE ) A
WHERE RN = 1

SELECT * FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY REQ, PO, LINE ORDER BY REV DESC) AS rw, REQ, PO, LINE, COST, REV
FROM #T1 ) x
WHERE rw = 1
use row number to get only the highest rev

SELECT t1.*
FROM TABLE t1
INNER JOIN (
SELECT REQ,PO,LINE,MAX(REV) AS REV
FROM TABLE
)t2
ON t1.REQ=t2.REQ
AND t1.PO=t2.PO
AND t1.LINE=t2.LINE
AND t1.REV=t2.REV
Update: Optimal Query
Learn more about RANKING FUNCTIONS
;WITH CTE AS
(SELECT REQ, PO, LINE, COST, REV, ROW_NUMBER() OVER (PARTITION BY REQ, PO, LINE ORDER BY REV DESC) AS rw
FROM TABLE)
SELECT REQ, PO, LINE, COST, REV
FROM CTE
WHERE rw = 1

Related

Get all transaction details of a user f their 2nd month of transaction

Trying to get the 2nd transaction month details for all the customers
Date User_id amount
2021-11-01 1 100
2021-11-21 1 200
2021-12-20 2 110
2022-01-20 2 200
2022-02-04 1 50
2022-02-21 1 100
2022-03-22 2 200
For every customer get all the records in the month of their 2nd transaction (There can be multiple transaction in a month and a day by a particular user)
Expected Output
Date User_id amount
2022-02-04 1 50
2022-02-21 1 100
2022-01-20 2 200
You can use dense_rank:
select Date, User_id, amount from
(select *, dense_rank() over(partition by User_id order by year(Date), month(date)) r
from table_name) t
where r = 2;
Fiddle
If dense_rank is an option you can:
with cte1 as (
select *, extract(year_month from date) as yyyymm
from t
), cte2 as (
select *, dense_rank() over (partition by user_id order by yyyymm) as dr
from cte1
)
select *
from cte2
where dr = 2
Note that it is possible to write the above using one cte.

Get time intervals where the process was on each stage on Jinja SQL

I need to get the intervals where a process was on each stage, and take into account when the process went back to a stage. For example:
stage_name
from_day
to_day
A
1
2
B
2
3
B
3
4
B
4
5
C
5
6
B
6
7
D
7
the process is currently on stage D
I want to get a table like this
stage_name
from_day
to_day
A
1
2
B
2
5
C
5
6
B
6
7
D
7
This is a gaps and islands problem and you may use the following approaches to solve this.
Approach 1
SELECT
stage_name,
MIN(from_day) as from_day,
MAX(to_day) as to_day
FROM (
SELECT
*,
ROW_NUMBER() OVER (ORDER BY from_day) - ROW_NUMBER() OVER (PARTITION BY stage_name ORDER BY from_day) as grp
FROM
my_table
) t1
GROUP BY stage_name,grp
ORDER BY from_day, stage_name;
stage_name
from_day
to_day
A
1
2
B
2
5
C
5
6
B
6
7
D
7
View working demo on DB Fiddle
Approach 2
SELECT
stage_name,
MIN(from_day) as from_day,
MAX(to_day) as to_day
FROM (
SELECT
*,
SUM(same) OVER (PARTITION BY stage_name ORDER BY from_day) as grp
FROM (
SELECT
*,
CASE
WHEN from_day = LAG(to_day,1,from_day) OVER (PARTITION BY stage_name ORDER BY from_day) THEN 0
ELSE 1
END as same
FROM
my_table
) t1
) t2
GROUP BY stage_name,grp
ORDER BY from_day, stage_name;
stage_name
from_day
to_day
A
1
2
B
2
5
C
5
6
B
6
7
D
7
View working demo on DB Fiddle
The example above uses from_day = LAG(to_day,1,from_day) OVER (PARTITION BY stage_name ORDER BY from_day) to determine if the current rows from_day is the same as the previous rows to_day within the same stage_name group/partition ordered by from_day. If it is the same 0 is assigned otherwise 1. The output of this subquery has been included below for your perusal:
SELECT
*,
CASE
WHEN from_day = LAG(to_day,1,from_day) OVER (PARTITION BY stage_name ORDER BY from_day) THEN 0
ELSE 1
END as same
FROM
my_table
ORDER BY from_day, stage_name;
stage_name
from_day
to_day
same
A
1
2
0
B
2
3
0
B
3
4
0
B
4
5
0
C
5
6
0
B
6
7
1
D
7
0
The window function SUM(same) OVER (PARTITION BY stage_name ORDER BY from_day) is then used to find the cumulative sum of these differences, thus creating groups:
SELECT
*,
SUM(same) OVER (PARTITION BY stage_name ORDER BY from_day) as grp
FROM (
SELECT
*,
CASE
WHEN from_day = LAG(to_day,1,from_day) OVER (PARTITION BY stage_name ORDER BY from_day) THEN 0
ELSE 1
END as same
FROM
my_table
) t1
ORDER BY from_day, stage_name;
stage_name
from_day
to_day
same
grp
A
1
2
0
0
B
2
3
0
0
B
3
4
0
0
B
4
5
0
0
C
5
6
0
0
B
6
7
1
1
D
7
0
0
Finally by grouping by the stage_name and grp we can find the desired values in each group, in this case the earliest from_day using MIN and the latest to_day using MAX

Get the maximum number of consecutive zeros SQL

I have below table. The months columns represent the number of orders each customer has placed. I want to calculate the maximum number of consecutive zeros.
customer_id
Jan
Feb
Mar
Apr
May
Jun
1
1
2
1
1
2
1
2
1
0
0
0
0
0
3
0
0
1
0
0
0
4
0
0
0
1
0
1
so the result table would be:
customer_id
cons_zeros
1
0
2
5
3
3
4
3
I know there is a window function like that can tackle consecutive 0s for rows but am unsure how to do it for columns.
I would suggest unpivoting, treating this as a gaps-and-islands problem, and then reaggregating:
select customerid,
max(case when val = 0 then cnt else 0 end) as max_zeros
from (select customerid, val, (n - seqnum), count(*) as cnt
from (select cn.*,
row_number() over (partition by customerid, val order by n) as seqnum
from (select customerid, 1 as n, jan as val from t union all
select customerid, 2 as n, feb as val from t union all
select customerid, 3 as n, mar as val from t union all
select customerid, 4 as n, apr as val from t union all
select customerid, 5 as n, may as val from t union all
select customerid, 6 as n, jun as val from t
) cn
) cn
group by customerid, val, (n - seqnum)
) cn
group by customerid;

SQL How to select the value of the end of season(every three month)

Supposed I have some data as below:
code vol val num test_date
------------------------------------------
1 00001 500 0.1 111 20180105
2 00001 1000 0.2 222 20180304
3 00001 200 0.1 111 20180330
4 00001 400 0.3 222 20180601
5 00001 200 0.2 333 20180630
My expected result is
code vol val num test_date
------------------------------------------
1 00001 200 0.1 111 20180330
2 00001 200 0.2 333 20180630
3 00001 200 0.2 333 20180928 -- Max(val) only 0928, there is no data in 20180930
4 00001 200 0.2 333 20181231
I would like to select the max(val) for the month in '3, 6, 9 12', how to query in MySQL, thanks so much for any advice.
Since your dates are in numeric YYYYMMDD form, you can convert them to a "season" by integer dividing the date by 300. You can then find the maximum test_date per season and JOIN that back to the original table to get the values for that date:
SELECT d.*
FROM data d
JOIN (SELECT test_date DIV 300 AS quarter, MAX(test_date) AS max_date
FROM data
GROUP BY quarter) m ON m.max_date = d.test_date
Demo on dbfiddle
You can use quarter function available in mysql.
select * from test t1
inner join (
select quarter(test_date) qtr, max(val) val from test
group by quarter(test_date)) t2 on t2.val = t1.val and t2.qtr = quarter(t1.test_date)
see dbfiddle.
Hmmm . . . If you want the maximum value for each quarter, you can use window functions:
select t.*
from (select t.*,
row_number() over (partition by year(test_date), quarter(test_date) order by val desc) as seqnum
from t
) t
where seqnum = 1;
If you want the value on the last day of the quarter that is in the data, then use order by test_date desc instead:
select t.*
from (select t.*,
row_number() over (partition by year(test_date), quarter(test_date) order by test_date desc) as seqnum
from t
) t
where seqnum = 1;

Select max(Data)

I have a table:
id cod_pr Date nr
-------------------------------
1 22 12.10.2012 2
2 25 12.10.2012 3
3 22 12.11.2012 5
4 25 12.11.2012 2
5 22 12.12.2012 4
6 23 12.10.2012 3
How kan I select only max Date from each cod_pr?
select cod_pr,MAX(Date) from Table
group by cod_pr
If you want all columns, you can use ROW_NUMBER in a CTE:
WITH CTE AS
(
SELECT id,cod_pr,Date,nr,
ROW_NUMBER() OVER (PARTITION BY cod_pr ORDER BY Date DESC) AS RN
FROM dbo.Table
)
SELECT id,cod_pr,Date,nr, FROM CTE WHERE RN = 1
Otherwise you can simply use GROUP BY
SELECT cod_pr, MAX(Date) AS MaxDate
FROM dbo.Table
GROUP BY cod_pr