get the previous row of a query - sql

Doing a select I get a row, and I would want to get the previous row in the table.
create table t1
id char(3),
dat datetime
);
id dat
a 2014-04-21
b 2014-10-01
c 2014-10-15
select id from t1 where id='c'
and wanted to find the previous row i.e. b

What about:
DECLARE #id CHAR(3)
SET #id = 'c'
select
id
from
table
where
id=#id
OR
id = (SELECT MAX(id) FROM table WHERE id < #id)

Get all the rows where id is not greater than the specified value, then limit the results to just the top two rows:
SELECT TOP (2)
id
FROM
t1
WHERE
id <= 'c'
ORDER BY
id DESC
;

Related

Finding Occurrence of the duplicate values

I have table with 3 columns (id, Name, Occurrence), I want to update the Occurrence column ,based on the id column, attached snap for the reference.
for example if my id column has "606" value 3 times then my occurrent column should have 3 against all the "606" value.
Below is the method which I tried.
I tried to find the duplicate values using group by and Having clause and saved it in a temp table and from there I tried to join the table value from the temp table.
you can use window functions in an updatable CTE for this.
You haven't supplied any actual sample data so this is untested, however the following should work:
with x as (
select Id, Occurence, count(*) over(partition by Id) qty
from Table
)
update x
set Occurence = Qty;
You can go for GROUP BY based approach also.
declare #TABLE TABLE(ID INT, NAME CHAR(3), occurance int null)
insert into #TABLE VALUES
(1,'AAA',NULL),(1,'AAA',NULL),(2,'CCC',NULL),(3,'DDD',NULL), (3,'DDD',NULL),(4,'EEE',NULL),(5,'FFF',NULL);
;WITH CTE_Table as
(
SELECT ID, COUNT(*) AS Occurance
FROM #table
group by id
)
UPDATE t
SET occurance = c.occurance
FROM #table t
INNER JOIN CTE_Table as c
on C.ID = T.ID
SELECT * FROM #TABLE
ID
NAME
occurance
1
AAA
2
1
AAA
2
2
CCC
1
3
DDD
2
3
DDD
2
4
EEE
1
5
FFF
1
You can use a CTE and calculate row number and update your table base on CTE
;WITH q
AS
(
SELECT Id,COUNT(1) 'RowNum'
FROM YourTable
GROUP BY Id
)
UPDATE YourTable
SET Occurrence=q.RowNum
FROM YourTable t
INNER JOIN q
ON t.Id=q.Id

Increment based on max value BigQuery

I have two tables.
TABLE A:
OBJECTID ID
NULL 41230
NULL 00004
NULL 00005
TABLE B:
OBJECTID ID
241231 00001
241230 00002
I'm trying to write a query that increments values for the OBJECTID field in Table A based on the max value in Table B. For example the OBJECTID field for the first row in Table A would then be 241232.
Using ROW_NUMBER() over (Order by OBJECTID ASC) works if I wanted to start with the value 1 and increment. But I need it to join on Table B and start on Table B's max value and then increment.
I've tried this but get a query error Query error: Table-valued function not found tableB:
UPDATE `tableA`
SET OBJECTID = (SELECT MAX(OBJECTID) as seq
FROM `tableB`
((SELECT ROW_NUMBER() over (Order by seq ASC))
)) WHERE OBJECTID IS NULL;
In BigQuery is easier create a new table that overwrite the actual. You can do it with this select:
with max_id as (
select max(objectid) as objectid from tableB
),
table_a_new_id as (
select
* except (objectid),
(select objectid from max_id) + dense_rank() over (order by id) as objectid
from tableA
where objectid is null
)
select * from table_a_new_id
union all
select * from tableA where objectid is not null
If you can't replace the table directly, you can save the result in a temporary table and then run the update:
update tableA
set tableA.objectid = new_table_a.objectid
from temp_new_tableA
where tableA.objectid is null and tableA.id = temp_new_tableA.id

Select until condition in sql

I've got a table
CREATE TABLE Table1(
Id INT NOT NULL IDENTITY(1,1),
EvType INT NOT NULL,
CreatedByUserId INT NOT NULL
)
Initial data:
And i wonna get only rows which meet the next condition: We select row until Id of the row will be less than first row with EvType == 200 per createdByUserId. So we need to select firsly all first rows for each user with evType == 200, which i've done in this way:
WITH EVS1 AS (
SELECT evs.Id, evs.EvType, evs.CreatedByUserId
ROW_NUMBER() OVER (PARTITION BY evs.CreatedByUserId ORDER BY evs.CreatedDate DESC) as rk
FROM [dbo].Table1 evs)
select *
From EVS1
WHERE EVS1.rk=1
Which produces the following result:
And then somehow i need to select rows for each user until Id is greater then row from CTE for that user, Is that possible to do that?
So we need to retrieve from that table rows until 4th included. Skip the 5th row cause it goes after the first user row with evType 200
Expected Result:
Find min(id) first and then the row having lower or equal id
SELECT *
FROM EVS1
WHERE id <= (SELECT MIN(id) FROM EVS1 WHERE evType = 200)
I assume that you define the ordering according to the id attribute.
If it is necessary to do it for each CreatedByUserId then use a dependent subquery for the minimal id computation
SELECT *
FROM EVS1 e1
WHERE id <= (
SELECT MIN(id)
FROM EVS1 e2
WHERE e2.evType = 200
and e1.CreatedByUserId = e2.CreatedByUserId
)
DBFIDDLE DEMO
I believe that this solution will be faster then a window function for a large data if you will have an index
CREATE INDEX ix_evs1_evType_CreatedByUserId ON evs1(evType, CreatedByUserId) INCLUDE(id)
You can do a window max:
select Id, EvType, CreatedByUserId
from (
select
t.*,
max(case when EvType = 200 then 1 else 0 end)
over(partition by CreatedByUserId order by Id) flagEvType
from [dbo].Table1
)
where flagEvType = 0
You want to select all rows created by a user except for those where an event type 200 occurred before:
select *
from mytable t1
where not exists
(
select null
from mytable t2
where t2.evtype = 200
and t2.createdbyuserid = t1.createdbyuserid
and t2.id < t1.id
);

SQL query to return rows where only one record is present in a given status

I have a table with data similar to below. I am trying to get a list of results that will display all rows where only one unique SourceID exists in status 10. If I were querying this table, I would expect ID's 3 and 4 to be returned.
Table Example
Select *
From table
Where Status = 10 and Source ID in
(
Select SourceID
From Table
Group by SourceID
Having Count(*) = 1
)
You can use NOT EXISTS :
SELECT t.*
FROM table t
WHERE NOT EXISTS (SELECT 1 FROM table t1 WHERE t1.SourceID = t.SourceID AND t1.Status <> t.Status);
Maybe that would work?
SELECT ID FROM Mytable
WHERE [Status] = 10
GROUP BY ID
HAVING COUNT(SourceID) = 1
First, find out all the unique SourceIDs
SELECT
SourceID
FROM
Data
GROUP BY
SourceID
HAVING
COUNT(SourceID) = 1
And then use this query as a sub query to get all the rows that has unique SourceID;
SELECT
*
FROM
Data
WHERE
SourceID IN (
SELECT
SourceID
FROM
Data
GROUP BY
SourceID
HAVING
COUNT(SourceID) = 1
)
Use a sub-query to check if t there is an exact count of 1 of those source id's
SELECT t.* FROM YourTable t WHERE t.status = 10
AND
(SELECT COUNT(0) x From YourTable t2
where t2.sourceid = t.sourceid) = 1

SQL: how to select next id given an id

There is one table T ( id integer, primary key ( id).
I want a parameterized query that, given id i:
will return next consecutive id,
if i = biggest id in T, query should return the smallest id in T (cyclical)
You can select the smallest id over the value #i (if any), and the smallest id, then get the largest:
select max(id)
from (
select top 1 id
from T
where id > #i
order by id
union all
select top 1 id
from T
order by id
) x
Or perhaps:
select max(id)
from (
select min(id) as id
from T
where id > #i
union all
select min(id)
from T
) x
This appears to be what you're looking for:
CREATE PROCEDURE dbo.ProcName
(
#ID INTEGER
)
AS
SELECT TOP 1 id
FROM table
WHERE id > #ID
ORDER BY id