If Rownumber = 1 and Condition Then Condition - sql

I've got a question about a sql result and how to achieve the following.
In the Screenshot, there is a Rownumber for every ID, and every ID has another column which has a status 'old' or 'processed'. What i want is, if the RN is = 1 and the Status is processed, than all other RN of this ID should also have the status 'processed'.
Is there a possibility to achieve this in sql?
SELECT RN = ROW_NUMBER() OVER (PARTITION BY [NODE_NAME]
ORDER by REPORTING_RELEVANT_STATUS_ID DESC, BILLING_PERIOD DESC)
,[CI_EQUIPMENT_ID] AS ID_PART
,[REPORTING_RELEVANT_STATUS_ID] AS REPORTING_RELEVANT
,[BILLING_PERIOD]
, [NODE_NAME]
FROM Table

Put your query in CTE? then JOIN it with actual table:
;WITH cte AS (
SELECT RN = ROW_NUMBER() OVER (PARTITION BY [NODE_NAME]
ORDER by REPORTING_RELEVANT_STATUS_ID DESC, BILLING_PERIOD DESC)
,[CI_EQUIPMENT_ID] AS ID_PART
,[REPORTING_RELEVANT_STATUS_ID] AS REPORTING_RELEVANT
,[BILLING_PERIOD]
, [NODE_NAME]
FROM Table
)
SELECT t.[CI_EQUIPMENT_ID] AS ID_PART,
CASE WHEN c.RN is NOT NULL THEN c.REPORTING_RELEVANT ELSE t.[REPORTING_RELEVANT_STATUS_ID] END AS REPORTING_RELEVANT,
t.[BILLING_PERIOD],
t.[NODE_NAME]
FROM Table t
LEFT JOIN (
SELECT *
FROM cte
WHERE RN = 1 AND REPORTING_RELEVANT = 'PROCESSED'
) as c
ON c.ID_PART = t.[CI_EQUIPMENT_ID]

Creating common table expression
Updating the CTE values based on RN=1 and Status=Processed. using the Self Join
here:
;with CTE (RN,ID_PART,REPORTING_RELEVANT,BILLING_PERIOD,NODE_NAME) AS
(
SELECT RN = ROW_NUMBER() OVER (PARTITION BY [NODE_NAME]
ORDER by REPORTING_RELEVANT_STATUS_ID DESC, BILLING_PERIOD DESC)
,[CI_EQUIPMENT_ID] AS ID_PART
,[REPORTING_RELEVANT_STATUS_ID] AS REPORTING_RELEVANT
,[BILLING_PERIOD]
, [NODE_NAME]
FROM Table
)
Update CTE1
set CTE1.Status='Processed'
from CTE CTE1 inner join CTE CTE2
on CTE1.ID_PART=CTE2.ID_PART
where CTE2.RN=1 and CTE2.Status='Processed'

Related

Selecting the latest order

I need to select the data of all my customers with the records displayed in the image. But I need to get the most recent record only, for example I need to get the order # E987 for John and E888 for Adam. As you can see from the example, when I do the select statement, I get all the order records.
You don't mention the specific database, so I'll answer with a generic solution.
You can do:
select *
from (
select t.*,
row_number() over(partition by name order by order_date desc) as rn
from t
) x
where rn = 1
You can use analytical function row_number.
Select * from
(Select t.*,
Row_number() over (partition by customer_id order by order_date desc) as rn
From your_table t) t
Where rn = 1
Or you can use not exists as follows:
Select *
From yoir_table t
Where not exists
(Select 1 from your_table tt
Where t.customer_id = tt.custome_id
And tt.order_date > t.order_date)
You can do it with a subquery that finds the last order date.
SELECT t.*
FROM yoir_table t
JOIN (SELECT tt.custome_id,
MAX(tt.order_date) MaxOrderDate
FROM yoir_table tt
GROUP BY tt.custome_id) AS tt
ON t.custome_id = tt.custome_id
AND t.order_date = tt.MaxOrderDate

Select most recent status for each ID and department code

I have the following table:
I want to get the most recent status for each dept_code that a CL_ID has. So the desired output would be this:
I have tried the following but this give me just the most recent status for each client and not each of their dept_codes.
SELECT *
FROM [CIMSHR6_MERGED].[dbo].[C3CLSTAT] C
INNER JOIN
(SELECT CLIENT_NUMBER, MAX(STATUS_DATE) AS SDATE
FROM [CIMSHR6_MERGED].[dbo].[C3CLSTAT]
GROUP BY CLIENT_NUMBER) X
ON X.CLIENT_NUMBER = C.CLIENT_NUMBER
AND X.SDATE = C.STATUS_DATE
ORDER BY C.CLIENT_NUMBER
Any help would be much appreciated. Thanks.
A convenient method that works in SQL Server is:
select top (1) cl.*
from [CIMSHR6_MERGED].[dbo].[C3CLSTAT] cl
order by row_number() over (partition by cl_id, dept_code order by status_date desc);
A method that is efficient with the right indexes in almost any database is:
select cl.*
from [CIMSHR6_MERGED].[dbo].[C3CLSTAT] cl
where cl.status_date = (select max(cl2.status_date)
from [CIMSHR6_MERGED].[dbo].[C3CLSTAT] cl2
where cl2.cl_id = cl.cl_id and cl2.dept_code = cl.dept_code
);
The right index is on (cl_id, dept_code, status_date).
I would also use ROW_NUMBER, but with a subquery:
SELECT CL_ID, Status_date, Status, Dept_code
FROM
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CL_ID, Dept_code ORDER BY Status_date DESC) rn
FROM CIMSHR6_MERGED].[dbo].[C3CLSTAT]
) t
WHERE rn = 1;
1) Firstly group everything on Dept_Code,CL_ID and assign rank for each row with in the group in descending order.
2) Select all the rows with rnk=1 which would display your desired result.
SELECT Z.CL_ID,
Z.Status_Date,
Z.Status,
Z.Dept_Code
FROM
(
SELECT *,
RANK() OVER( PARTITION BY Dept_Code,CL_ID, ORDER BY Status_Date DESC ) AS rnk
FROM [CIMSHR6_MERGED].[dbo].[C3CLSTAT]
) Z
WHERE Z.rnk = 1;
This would work for almost all databases
select * from c3clstat c
where exists
(select 1 from c3clstat c1
where c1.cl_id=c.cl_id
and c1.dept_code=c.dept_code
group by cl_id,dept_code
having c.status_date=max(c1.status_date)
)

Max and Min row numbers from single cte code block

;with cte1 as
( select id,
row_number() over (partition by pk,pp,sn order by id asc)
as rn
from mqms_production
) select * into #M from cte1 where rn=1
With the above, I get all the rows with rn=1 but I also want to copy to another table all the rows with max rn for a given partition pk,pp, sn.
Is it possibleto do it without having to write the cte block again with
(partition by pk,pp,sn order by id DESC)
thanks!
You can just add another window function based expression there with reverse sort order and get the top rows on both of them
with cte1 as (
select id,
row_number() over (partition by pk,pp,sn order by id asc) as rn1,
row_number() over (partition by pk,pp,sn order by id desc) as rn2
from mqms_production
)
select * from cte1
where rn1 = 1 or rn2 = 1;

T-SQL select into temp table does not have correct result

-- This Result Is Right and work correctly:
SELECT AutoId, Name,[Group],[Priority], SUMCalculatedPercent
FROM
(SELECT DISTINCT *,
ROW_NUMBER() OVER
(
PARTITION BY [Group] ORDER BY SUMCalculatedPercent DESC,[Priority]
)
AS ranker
FROM #GroupMasterNameChoose
)Z
WHERE ranker = 1
ORDER BY Z.SUMCalculatedPercent DESC,Z.[Priority]
-- This Result Is Wrong :
SELECT AutoId, Name,[Group],[Priority], SUMCalculatedPercent
INTO #GroupOwner
FROM
(SELECT DISTINCT *,
ROW_NUMBER() OVER
(
PARTITION BY [Group] ORDER BY SUMCalculatedPercent DESC,[Priority]
)
AS ranker
FROM #GroupMasterNameChoose
)Z
WHERE ranker = 1
ORDER BY Z.SUMCalculatedPercent DESC,Z.[Priority]
--
Problem : I Need Store My Right Result To Temp Table
Remove ORDER BY Z.SUMCalculatedPercent DESC,Z.[Priority]

How to get the row that holds the last value in a queue of identical values? (SQL)

I think it's easier to show you an image:
So, for each fld_call_id, go to the next value, if it's identical. When we get to the last value, I need the value in column fld_menu_id.
Or, to put it in another way, eliminate fld_call_id duplicates and save only the last one.
You can use ROW_NUMBER:
WITH CTE AS(
SELECT RN = ROW_NUMBER() OVER (PARTITION BY fld_call_id ORDER BY fld_id DESC),
fld_menu_id
FROM dbo.TableName
)
SELECT fld_menu_id FROM CTE WHERE RN = 1
You can create a Rank column and only select that row, something along the lines of the following:
;WITH cte AS
(
SELECT
*
,RANK() OVER (PARTITION BY fld_call_id ORDER BY fld_id DESC) Rnk
FROM YourTable
)
SELECT
*
FROM cte
WHERE Rnk=1
So you GROUP BY fld_call_id and ORDER BY fld_id in descending order so that the last value comes first. These are the rows where Rnk=1.
Edit after comments of OP.
SELECT Table.*
FROM Table
INNER JOIN
(
SELECT MAX(fldMenuID) AS fldMenuID,
fldCallID
FROM Table
GROUP BY fldCallID
) maxValues
ON (maxValues.fldMenuID = Table.fldMenuID
AND maxValues.fldCallID= Table.fldCallID)
Hope This works
SELECT A.*
FROM table A
JOIN (SELECT fld_id,
ROW_NUMBER() OVER (PARTITION BY Fld_call_id ORDER BY fld_id DESC) [Row]
FROM table) LU ON A.fld_id = LU.fld_id
WHERE LU.[Row] = 1