Find last row in group by query-SQL Server - sql

I have table in SQL Server. I want to find last row in each group. I tried with the following query, but it does not return exact result. ID column is PK and other columns are set to NOT NULL.
select ID, Name FROM
(select ID, Name, max(ID) over (partition by Name) as MAX_ID
from Customer) x where ID= MAX_ID
To be more clear. I have 2 queries.First:
ALTER PROCEDURE [dbo].[Ramiz_Musterija_RowNum]
#Datum DATE,
#BrojKamiona INT
AS SET NOCOUNT ON
SELECT Ime,MusterijaID,RowNum=ROW_NUMBER() OVER(ORDER BY Ime)FROM Musterije
WHERE Datum=#Datum AND BrojKamiona=#BrojKamiona GROUP BY Ime,MusterijaID
And second one:
ALTER PROCEDURE [dbo].[Ramiz_Musterija_FindLast]
#Datum DATE,
#BrojKamiona INT
AS SET NOCOUNT ON
SELECT a.* from Musterije a
JOIN (SELECT Ime, MAX(MusterijaID) AS MAXID FROM Musterije GROUP BY Ime) AS b
ON a.MusterijaID = b.MAXID AND a.Datum=#Datum AND a.BrojKamiona=#BrojKamiona
Then LINQ query:
var rowNumList = from f in customerFindLastList
join r in customerRowNumList
on f.MusterijaID equals r.MusterijaID
select new { r.RowNum };
I am trying to find last row in each row,then match this 2 queries on MusterijaID column.
Any help regarding this would be appreciated.
This is output of one group. Now, problem is that these two queries are matched on "4250" MusterijaID, but I need to match queries on "4229".
Ime MusterijaID
100//1 4246
100//1 4247
100//1 4248
100//1 4249
100//1 4250
100//1 4229

select ID, Name
FROM (select ID, Name, -- add other columns here
ROW_NUMBER() over (partition by Name ORDER BY ID DESC) as MAX_ID
from Customer) x
WHERE MAX_ID = 1

Related

How to set identity seed value using variable in SQL Server

I have a table with columns id, items:
ID Items
----------------
1 mc3
2 mc2
3 mc1
I want to insert this data into a temp table but the order of items in descending i.e
ID Items
--------------
1 mc1
2 mc2
3 mc3
but I can't take order by of these items. items column has duplicate values. I tried to use identity column but that was a terrible idea. I will show that query.
DECLARE #totalNO INT = 0
SET #totalNO = (SELECT COUNT(*) FROM #tblmc)
SELECT IDENTITY(INT, #totalNO, -1) RowIndex1, *
INTO #tempmcfordesc
FROM #tblmc.
but this query causes an error. Is there any other way? I can loop the table and insert but I just want to know is there any easy way for this. Please sort this out.
if you have create the temp table then use this :
INSERT INTO #temptable
SELECT Row_Number()
OVER (
ORDER BY ID DESC) AS ID,
Items
FROM yourtable
and if you haven't created the temp table then create it with data like this :
SELECT Row_Number()
OVER (
ORDER BY ID DESC) AS ID,
Items
INTO #temptable
FROM yourtable

Select a NON-DISTINCT column in a query that return distincts rows

The following query returns the results that I need but I have to add the ID of the row to then update it. If I add the ID directly in the select statement it will return me more results then I need because each ID is unique so the DISTINCT statement see the line as unique.
SELECT DISTINCT ucpse.MemberID, ucpse.ProductID, ucpse.UserID
FROM UserCustomerProductSalaryExceptions as ucpse
WHERE EXISTS (SELECT NULL
FROM UserCustomerProductSalaryExceptions as upcse2
WHERE ucpse.userid = upcse2.userid AND ucpse.MemberID = upcse2.MemberID AND ucpse.ProductID = upcse2.ProductID
GROUP BY upcse2.UserID, upcse2.memberid, upcse2.productid
HAVING COUNT(UserID) >= 2
)
So basically I need to add ucpse.ID in the Select statement while keeping DISTINCT values for MemberID,ProductID and UserID.
Any Ideas ?
Thank you
According to you comment:
If the data has been duplicated 67 times for a given employee with a given product and a given client, I need to keep only one of thoses records. It's not important which one, so this is why I use DISTINC to obtain unique combinaison of given employee with a given product and a given client.
You can use MIN() or MAX() and GROUP BY instead of DISTINCT
SELECT MAX(ucpse.ID) AS ID, ucpse.MemberID, ucpse.ProductID, ucpse.UserID
FROM UserCustomerProductSalaryExceptions as ucpse
WHERE EXISTS (SELECT NULL
FROM UserCustomerProductSalaryExceptions as upcse2
WHERE ucpse.userid = upcse2.userid AND ucpse.MemberID = upcse2.MemberID AND ucpse.ProductID = upcse2.ProductID
GROUP BY upcse2.UserID, upcse2.memberid, upcse2.productid
HAVING COUNT(UserID) >= 2
)
GROUP BY ucpse.MemberID, ucpse.ProductID, ucpse.UserID
UPDATE:
From you comments I think the below query is what you need
DELETE FROM UserCustomerProductSalaryExceptions
WHERE ID NOT IN ( SELECT MAX(ucpse.ID) AS ID
FROM #UserCustomerProductSalaryExceptions
GROUP BY ucpse.MemberID, ucpse.ProductID, ucpse.UserID
HAVING COUNT(ucpse.ID) >= 2
)
If all you want is to delete the duplicates, this will do it:
WITH X AS
(SELECT ID,
ROW_NUMBER() OVER (PARTITION BY MemberID, ProductID, UserID ORDER BY ID) AS DupRowNum<br
FROM UserCustomerProductSalaryExceptions
)
DELETE X WHERE DupRowNum > 1
ID's not necessary - try:
UPDATE uu SET
<your settings here>
FROM UserCustomerProductSalaryExceptions uu
JOIN ( <paste your entire query above here>
) uc ON uc.MemberID=uu.MemberId AND uc.ProductID=uu.ProductId AND uc.UserID=uu.UserId
From the sound of your data structure (which I would STRONGLY advise normalizing as soon as possible), it sounds like you should be updating all the records. It sounds as if each duplicate is important because it contains some information about an employee's relation to a customer or product.
I would probably update all the records. Try this:
UPDATE UCPSE
SET
--Do your updates here
FROM UserCustomerProductSalaryExceptions as ucpse
JOIN
(
SELECT UserID, MemberID, ProductID
FROM UserCustomerProductSalaryExceptions
GROUP BY UserID, MemberID, ProductID
HAVING COUNT(UserID) >= 2
) T
ON ucpse.UserID = T.UserID AND ucpse.MemberID = T.MemberID AND ucpse.ProductID = T.ProductID

SQL Auto Increment a value with multiple inserts

We have a SQL query being executed against a SQL Server 2008 DB.
INSERT INTO ListDetail(ListID, Sequence, CompName, CompAddress, Date)
(
SELECT
12345 AS 'ListID',
(MAX(ListDetail.Sequence) + 1) AUTO_INCREMENT as 'Sequence',
Company.Name AS 'CompName',
Company.Address AS 'CompAddress',
GETDATE() AS 'Date'
FROM Company
WHERE CompanyType = 3
)
We want to find the max Sequence from ListDetail table.. and select records from the Company table into ListDetail. But, we want to start with the next available Sequence value from ListDetail and then increment by 1 for each record inserted. The Sequence field in ListDetail is just a general INT field.
We do not have control over the database its-self... so created a new table or altering the existing one is not an option.
One option would be to use Row_Number() with a subquery that returns the max():
Simplified solution:
insert into ListDetail
select 12345, sq+row_number() over (order by (select null))
from company, (select max(sequence) sq from listdetail) t
SQL Fiddle Demo
INSERT INTO ListDetail(ListID, Sequence, CompName, CompAddress, Date)
SELECT
12345,
sq+row_number() over (order by (select null)),
Name,
Address,
GETDATE()
FROM Company, (select max(sequence) sq from listdetail) t
WHERE CompanyType = 3
A simple approach like this should work for you.
INSERT INTO ListDetail(ListID, Sequence, CompName, CompAddress, Date)
(
SELECT
12345,
(SELECT MAX(Sequence) + 1 FROM ListDetail),
Company.Name,
Company.Address,
GETDATE()
FROM Company
WHERE CompanyType = 3
)

SQL Select highest values from table on two (or more) columns

not sure if there's an elegant way to acheive this:
Data
ID Ver recID (loads more columns of stuff)
1 1 1
2 2 1
3 3 1
4 1 2
5 1 3
6 2 3
So, we have ID as the Primary Key, the Ver as the version and recID as a record ID (an arbitary base ID to tie all the versions together).
So I'd like to select from the following data, rows 3, 4 and 6. i.e. the highest version for a given record ID.
Is there a way to do this with one SQL query? Or would I need to do a SELECT DISTINCT on the record ID, then a seperate query to get the highest value? Or pull the lot into the application and filter from there?
A GROUP BY would be sufficient to get each maximum version for every recID.
SELECT Ver = MAX(Ver), recID
FROM YourTable
GROUP BY
recID
If you also need the corresponding ID, you can wrap this into a subselect
SELECT yt.*
FROM Yourtable yt
INNER JOIN (
SELECT Ver = MAX(Ver), recID
FROM YourTable
GROUP BY
recID
) ytm ON ytm.Ver = yt.Ver AND ytm.recID = yt.RecID
or, depending on the SQL Server version you are using, use ROW_NUMBER
SELECT *
FROM (
SELECT ID, Ver, recID
, rn = ROW_NUMBER() OVER (PARTITION BY recID ORDER BY Ver DESC)
FROM YourTable
) yt
WHERE yt.rn = 1
Getting maximum ver for a given recID is easy. To get the ID, you need to join on a nested query that gets these maximums:
select ID, ver, recID from table x
inner join
(select max(ver) as ver, recID
from table
group by recID) y
on x.ver = y.ver and x.recID = y.recID
You could use a cte with ROW_NUMBER function:
WITH cte AS(
SELECT ID, Ver, recID
, ROW_NUMBER()OVER(PARTITION BY recID ORDER BY Ver DESC)as RowNum
FROM data
)
SELECT ID,Ver,recID FROM cte
WHERE RowNum = 1
straighforward example using a subquery:
SELECT a.*
FROM tab a
WHERE ver = (
SELECT max(ver)
FROM tab b
WHERE b.recId = a.recId
)
(Note: this assumes that the combination of (recId, ver) is unique. Typically there would be a primary key or unique constraint on those columns, in that order, and then that index can be used to optimize this query)
This works on almost all RDBMS-es, although the correlated subquery might not be handled very efficiently (depending on RDBMS). SHould work fine in MS SQL 2008 though.

How to get one unique record from the same list of records from table? No Unique constraint in the table

I have one query in SQL Server output,
Suppose i have one table (Ex.StudentMaster) having some fields-No unique constraints.
For Ex. RollNumber and Name
The table has same same data. For ex:
RollNo Name
1 Yoko
1 Yoko
1 Yoko
I want to get only third record. How can i identify this unique record?
Any row is a third row :-)
create table test
(
n int,
name varchar(30)
);
insert into test values(1,'yoko'),(1,'yoko'),(1,'yoko');
select ROW_NUMBER() over(order by name) as ordinal, * from test;
Deleting the "third" row :-)
with a as
(
select ROW_NUMBER() over(order by name) as ordinal, * from test
)
delete from a where a.ordinal = 3
Deleting the last row:
with a as
(
select ROW_NUMBER() over(order by name) as ordinal, * from test
)
delete from a where a.ordinal = (select MAX(ordinal) from a)
You can use DISTINCT which return's distinct combination's of columns.
SELECT DISTINCT RollNo, Name
FROM mytable