How to select only incremental records in BIG QUERY - sql

I have a data in my database like as follows
and i am expecting the result like
Can anyone please help me how to write a select query for this. it is a kind of incremental load of data
Please help me on this

You can use window functions. You want the earliest version of each record, so:
select t.*
from (select t.*,
row_number() over (partition by empid, empname, sal order by create_time) as seqnum
from t
) t
where seqnum = 1;
If you want to detect changes, rather than the first occurrence of a set of values, you can use lag():
select t.*
from (select t.*,
lag(sal) over (partition by empid, empname order by create_time) as prev_sal
from t
) t
where prev_sal is null or prev_sal <> sal;
This handles salaries that decrease as well as increase.

SQL SERVER or ORACLE?
here I try for SQL SERVER
for all records, get the most recent previous record for the employee (if any) and check for changes since then, if none, do not select - therefore, only new or changed records are shown
SELECT t1.* FROM tab t1
OUTER APPLY
(SELECT TOP 1 t2.*
FROM tab t2
WHERE t1.empid = t2.empid
AND t2.create_time < t1.create_time
ORDER BY t2.create_time DESC
) IQ
WHERE IQ.empid IS NULL
OR IQ.ename != t1.ename
OR IQ.sal != t1.sal

Related

SQL - Only need the record with Max Date

My table looks something like this:
I want to get the record for the MAX Date. So after querying, my output should only contain this:
A correlated subquery is a simple method:
select t.*
from t
where t.update_date = (select max(t2.update_date) from t t2 where t2.number = t.num);
Use row_number() with top (1) with ties available for SQL Server (which was initially tagged) :
select top (1) with ties t.*
from table t
order by row_number() over (partition by no order by date desc);
You can also use subquery :
select t.*
from (select t.*, row_number() over (partition by no order by date desc) as seq
from table t
) t
where seq = 1;

Is there SQL Query using SQL Server 2016 to display only record with no duplicates?

I have
How to query so that the results will only display record having no duplicate without hard coding? See results
If you want empcodes with no duplicates, then one simple way uses aggregation:
select empcode, min(leavecode) as leavecode
from t
group by empcode
having count(*) = 1;
This works, because if there is only one row for an empcode, then min(leavecode) is the leavecode.
An alternative method uses window functions:
select empcode, leavecode
from (select t.*, count(*) over (partition by empcode) as cnt
from t
) t
where cnt = 1;
Or, if leavecodes are unique when there are duplicates, perhaps the most efficient way:
select t.*
from t
where not exists (select 1
from t t2
where t2.emp_code = t.empcode and t2.leavecode <> t.leavecode
);
You just select those records that have the empcode in a table of empcodes that only have one occurrence.
SELECT
empcode,
leavecode
FROM mytable
WHERE empcode in (
SELECT empcode FROM mytable GROUP BY empcode HAVING count(1)=1
)

SQL Server Group By with Max on Date field

I hope i can explain the issue i'm having and hopefully so can point me in the same direction.
I'm trying to do a group by (Email Address) on a subset of data, then i'm using a max() on a date field but because of different values in other fields its bring back more rows then require.
I would just like to return the max record per email address and return the fields that are on the same row that are on the max record.
Not sure how i can write this query?
This is a task for ROW_NUMBER:
select *
from
(
select t.*,
-- assign sequential number starting with 1 for the maximum date
row_number() over (partiton by email_address order by datecol desc) as rn
from tab
) as dt
where rn = 1 -- only return the latest row
You can write this query using row_number():
select t.*
from (select t.*,
row_number() over (partition by emailaddress order by date desc) as seqnum
from t
) t
where seqnum = 1;
How about something like this?
select a.*
from baseTable as a
inner join
(select Email,
Max(EmailDate) as EmailDate
from baseTable
group by Email) as b
on a.Email = b.Email
and a.EmailDate = b.EmailDate

How to select a row based on its row number?

I'm working on a small project in which I'll need to select a record from a temporary table based on the actual row number of the record.
How can I select a record based on its row number?
A couple of the other answers touched on the problem, but this might explain. There really isn't an order implied in SQL (set theory). So to refer to the "fifth row" requires you to introduce the concept
Select *
From
(
Select
Row_Number() Over (Order By SomeField) As RowNum
, *
From TheTable
) t2
Where RowNum = 5
In the subquery, a row number is "created" by defining the order you expect. Now the outer query is able to pull the fifth entry out of that ordered set.
Technically SQL Rows do not have "RowNumbers" in their tables. Some implementations (Oracle, I think) provide one of their own, but that's not standard and SQL Server/T-SQL does not. You can add one to the table (sort of) with an IDENTITY column.
Or you can add one (for real) in a query with the ROW_NUMBER() function, but unless you specify your own unique ORDER for the rows, the ROW_NUMBERS will be assigned non-deterministically.
What you're looking for is the row_number() function, as Kaf mentioned in the comments.
Here is an example:
WITH MyCte AS
(
SELECT employee_id,
RowNum = row_number() OVER ( order by employee_id )
FROM V_EMPLOYEE
ORDER BY Employee_ID
)
SELECT employee_id
FROM MyCte
WHERE RowNum > 0
There are 3 ways of doing this.
Suppose u have an employee table with the columns as emp_id, emp_name, salary. You need the top 10 employees who has highest salary.
Using row_number() analytic function
Select * from
( select emp_id,emp_name,row_number() over (order by salary desc) rank
from employee)
where rank<=10
Using rank() analytic function
Select * from
( select emp_id,emp_name,rank() over (order by salary desc) rank
from employee)
where rank<=10
Using rownum
select * from
(select * from employee order by salary desc)
where rownum<=10;
This will give you the rows of the table without being re-ordered by some set of values:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT '1')) AS RowID, * FROM #table
If using SQL Server 2012 you can now use offset/fetch:
declare #rowIndexToFetch int
set #rowIndexToFetch = 0
select
*
from
dbo.EntityA ea
order by
ea.Id
offset #rowIndexToFetch rows
fetch next 1 rows only

SQL Server select first instance of ranked data with a twist

I have a Table1 that look like this:
Wallet No Status Rank
01774076563 Scanned 1
01765653275 Registered 3
01774076563 Accepted 2
01768836816 Rejected 4
01967866981 Accepted 2
01967866981 Rejected 4
I want it to look like this (Table2):
Wallet No Status Rank
01774076563 Scanned 1
01765653275 Registered 3
01768836816 Rejected 4
01967866981 Accepted 2
I have used following code but it shows Table1 instead of Table2:
SELECT MIN([Rank]) AS [Rank], STATUS_, walletno into table2
FROM table1
GROUP BY STATUS_, walletno
What I want is only the highest ranking wallet no and status, nothing else. But the Table2 gives me exact copy of Table1. What am I doing wrong here?
You are looking for the complete row, rather than just the minimum value. For this, the window functions are handy.
Because your logic uses min(), here is a method using that function:
SELECT [Rank], STATUS_, walletno into table2
FROM (select t.*,
MIN([rank]) over (partition by walletno) as minrank
from table1 t
) t
where [rank] = minrank;
The subquery calculates the minimum rank for each wallet. The outer filter than keeps only that row.
I would normally write this with row_number() as:
SELECT [Rank], STATUS_, walletno into table2
FROM (select t.*,
row_number() over (partition by walletno order by [rank]) as seqnum
from table1 t
) t
where seqnum = 1;
But the two should be pretty similar in terms of performance. The major difference is when two rows have the same minimum rank. The first version will return both rows. The second will arbitrarily choose one of them.
You can try this:
;WITH CTE as
(
SELECT
WalletNo,
Status,
ROW_NUMBER() OVER(PARTITION BY Status ORDER BY Rank) AS Row,
Rank
FROM
Item
)
SELECT WalletNo, Status, Row, Rank From CTE Where Row = 1
Fiddle here: http://sqlfiddle.com/#!3/14fa5/6