Apply Sequence based on unique_id - sql

I have a table:
table1
unique_id col_id val_id
1 100 a
1 101 b
1 102 c
1 103 d
2 106 a
2 106 b
2 104 c
2 103 d
I want to use a sequence to assign it for each unique_id.
I wrote the following which doesn't seem to work:
SELECT
my_seq.NEXTVAL over
(
PARTITION BY a.unique_id ORDER by a.unique_id) AS rec_i,
a.* FROM table1
a;
The output would be:
unique_id col_id val_id rec_i
1 100 a 123
1 101 b 123
1 102 c 123
1 103 d 123
2 106 a 124
2 106 b 124
2 104 c 124
2 103 d 124
How can I make it work?

Try this:
-- data preparation
create table tt_table (unique_id number, col_id number, val_id varchar2(1));
insert into tt_table values(1,100,'a');
insert into tt_table values(1,101,'b');
insert into tt_table values(1,102,'c');
insert into tt_table values(1,103,'d');
insert into tt_table values(2,106,'a');
insert into tt_table values(2,104,'b');
insert into tt_table values(2,103,'c');
insert into tt_table values(2,103,'d');
-- creating function
CREATE OR REPLACE FUNCTION GET_SEQ RETURN NUMBER AS
BEGIN
RETURN TEJASH_SEQ.NEXTVAL;
END GET_SEQ;
/
--
-- actual query
--
WITH T2 AS (
SELECT /*+ materialize */
UNIQUE_ID,
GET_SEQ SEQ_VALUE
FROM
(
SELECT DISTINCT
UNIQUE_ID
FROM
TT_TABLE
) T2IN
)
SELECT
T1.UNIQUE_ID,
T1.COL_ID,
T1.VAL_ID,
T2.SEQ_VALUE
FROM
TT_TABLE T1,
T2
WHERE
T1.UNIQUE_ID = T2.UNIQUE_ID
ORDER BY
T1.UNIQUE_ID;
Hope it is helpful.

Related

sql data where not exists in a table and not duplicate

its a bit tricky please focus on my requirments, I have 2 tables , I want to get data from first table where not exists in the second AND the data in first column are not duplicate for sub id and child id.
example: I have this table
tab1
id subid childid
1 11 77
2 22 55
3 33 66
4 11 77
7 22 55
8 33 60
9 99 98
10 33 60
11 97 98
tab2
id
1
4
7
10
the first thing I want is the id in tab1 doesnt exists in tab2 which will be
2,3,8,9,11 however some of those id have duplicate subid and chilid so i have to exclude them therefore I should have id 3, 9, 11
I tried this query but it returne me also 3 ,9 ,11, 8 , I dont want 8 how to fix the query ?
select *
from tab1 a
where not exists (select 1 from tab2 b where a.id = b.id)
and a.sub_id in (select c.sub_id
from tab1 c
group by c.sub_id,c.evt_id
having count(1) = 1)
For multiple database vendors I think the easiest solution would be a couple of not exists queries:
select *
from tab1 a
where not exists (
select 1
from tab2 b
where a.id = b.id
)
and not exists (
select 1
from tab1 c
where c.sub_id = a.sub_id
and c.evt_id = a.evt_id
and c.id <> a.id
)
i think below query will work
select a.*
from tab1 a
where not exists (select 1 from tab2 b where a.id = b.id)
and not exists (select 1 from tab1 c
where c.sub_id = a.sub_id
and c.childid = a.childid
group by c.sub_id,childid
having count(*)> = 2
)
Just to add an approach using a CTE, you can first determine the unique childid,subid pairs and then join that table with your main table:
DB Fiddle
Schema (PostgreSQL v9.6)
create table tab1 (
id integer primary key unique not null
, subid integer not null
, childid integer not null
);
insert into tab1 (id,subid,childid) values (1, 11, 77);
insert into tab1 (id,subid,childid) values (2, 22, 55);
insert into tab1 (id,subid,childid) values (3, 33, 66);
insert into tab1 (id,subid,childid) values (4, 11, 77);
insert into tab1 (id,subid,childid) values (7, 22, 55);
insert into tab1 (id,subid,childid) values (8, 33, 60);
insert into tab1 (id,subid,childid) values (9, 99, 98);
insert into tab1 (id,subid,childid) values (10, 33,60);
insert into tab1 (id,subid,childid) values (11, 97 ,98);
create table tab2 (
id integer primary key unique not null
);
insert into tab2 (id) values (1);
insert into tab2 (id) values (4);
insert into tab2 (id) values (7);
insert into tab2 (id) values (10);
Query #1
with tab1_unique as (
select subid, childid, count(*) as duplicate
from tab1
group by subid, childid
having count(*) = 1
)
select *
from tab1 a
join tab1_unique u on a.subid = u.subid and a.childid = u.childid
where not exists (select 1 from tab2 b where a.id = b.id);
| id | subid | childid | subid | childid | duplicate |
| --- | ----- | ------- | ----- | ------- | --------- |
| 11 | 97 | 98 | 97 | 98 | 1 |
| 9 | 99 | 98 | 99 | 98 | 1 |
| 3 | 33 | 66 | 33 | 66 | 1 |
not exists should do this:
select t1.*
from (select t1.*, count(*) over (partition by subid, childid) as cnt
from tab1 t1
) t1
where not exists (select 1 from tab2 t2 where t2.id = t1.id) and
cnt = 1;
You can use not exists as well for the subid/childid with the assumption that the rows are unique in the first table. Without this assumption, window functions are best solution -- and possibly the best solution anyway.

SQL Server show non matching records

I have table like below .
create table #test (NAME varchar(100),TAGint,checkVAL varchar(1),CATEGORY int)
insert into #test values('jkl',1,'y',100)
insert into #test values('abc',1,'y',100)
insert into #test values('abc',1,'y',101)
insert into #test values('abc',2,'n',102)
insert into #test values('abc',3,'n',103)
insert into #test values('xyz',2,'y',104)
insert into #test values('xyz',1,'y',105)
insert into #test values('pqr',1,'y',105)
insert into #test values('pqr',1,'y',106)
insert into #test values('pqr',1,'y',106)
Now I want to show those records which have diffrent values in columns name , tag , checkVal .
This is what I have done.
select * from #test
;with cte as
(
select *,row_number() over(partition by NAME,TAG,checkVAL order by CATEGORY ) as rownum
from #test
)
select * from cte
where rownum=1
This is what is being returned
NAME TAG checkVAL CATEGORY rownum
-----------------------------------------
abc 1 y 100 1
abc 2 n 102 1
abc 3 n 103 1
jkl 1 y 100 1 --> This row should not come
pqr 1 y 105 1 --> This row should not come
xyz 1 y 105 1
xyz 2 y 104 1
What I am trying is that for any value in column NAME , if values are different in TAG or checkVAL or both , then those rows should only be shown.
Below row
jkl 1 y 100 1
Should not be shown because jkl has no other row to match.
Below row should not be shown
pqr 1 y 105 1
because all rows with NAME column value as pqr have same values in TAG and checkVAL columns
I want to preferably approach using CTE .
How about this -
select
*
from #test a
where exists
(
select *
from
#test b
where a.name = b.name and (a.tag <> b.tag or a.checkVAL <> b.checkVAL)
)

update oldID field based on fields in the same table

I need help with the following query.
create table #table1
(id int not null primary key identity,
customer_name varchar(25),
usage float,
oldID int null
)
insert into #table1 values('ABC',46.5,null)
insert into #table1 values('ABC',46.5,null)
insert into #table1 values('DEF',36.8,null)
insert into #table1 values('XYZ',50.1,null)
insert into #table1 values('DEF',36.8,null)
insert into #table1 values('XYZ',50.1,null)
select * from #table1
I want my table to be updated like this
id customer_name usage oldID
----------- ------------------------- ---------------------- -----------
1 ABC 46.5 NULL
2 ABC 46.5 1
3 DEF 36.8 NULL
4 XYZ 50.1 NULL
5 DEF 36.8 3
6 XYZ 50.1 4
The two records with the same name and usage means the later record was renewed.
In the new record the oldID field should point to its old record (ID).
Although in my actual table, I have a bunch of date fields which I probably can use but this would help me for now.
Try this using a CTE:
;WITH data AS
(
SELECT
id, customer_name,
OldID = (SELECT MIN(id) FROM #table1 t2 WHERE t2.customer_name = t.customer_name)
FROM #table1 t
)
UPDATE #table1
SET OldID = data.OldID
FROM Data
WHERE
data.customer_Name = #table1.customer_name
AND #table1.ID <> data.oldid
select * from #table1
The Data CTE basically just determines the minimum ID for each customer, and if that customer's ID isn't that minimum ID, then OldID is set to that ID value.
When I run this, I get a resulting output:
id customer_name usage oldID
1 ABC 46.5 NULL
2 ABC 46.5 1
3 DEF 36.8 NULL
4 XYZ 50.1 NULL
5 DEF 36.8 3
6 XYZ 50.1 4
With cte, without subquerys, updating only customers with several rows:
with cte as (
select customer_name, min( id ) as id
from #table1
group by customer_name
having count(*) > 1
)
update #table1
set oldID = cte.id
from cte
where #table1.customer_name = cte.customer_name
and #table1.id != cte.id

MS Access "Group by" continuous values

I Have the following Access table (Primary Key = Date+Id):
Date Id Value
01/07/2011 00:10:00 5 200
01/07/2011 00:30:00 5 210
01/07/2011 00:40:00 2 458
01/07/2011 00:50:00 2 500
01/07/2011 01:00:00 4 600
01/07/2011 01:10:00 5 359
01/07/2011 01:20:00 5 360
01/07/2011 01:30:00 5 370
01/07/2011 01:40:00 5 380
Of course, the query "SELECT Id, MAX(Value) FROM DATAS GROUP BY Id;" returns:
Id Max
2 500
4 600
5 380
But is it possible in MS Access to have a query which groups by "sequences" of Id?
Expected result:
Id Max
5 210
2 500
4 600
5 380
There is no easy way to solve your problem. Here is a workaround.
declare #t table(date datetime, id int, value int)
insert #t values('01/07/2011 00:10:00',5,200)
insert #t values('01/07/2011 00:30:00',5,210)
insert #t values('01/07/2011 00:40:00',2,458)
insert #t values('01/07/2011 00:50:00',2,500)
insert #t values('01/07/2011 01:00:00',4,600)
insert #t values('01/07/2011 01:10:00',5,359)
insert #t values('01/07/2011 01:20:00',5,360)
insert #t values('01/07/2011 01:30:00',5,370)
insert #t values('01/07/2011 01:40:00',5,380)
;with a as
(
select date, id, value, (select count(*) from #t where t.date > date) rn
from #t t
), b as
(
select a.date, a.id, a.value, coalesce(cast(b.id - a.id as bit),1) d
from a left join a b on a.rn -1 = b.rn
), c as
(
select date,id, value, (select sum(d) from b b2 where date <=b.date) e from b
)
select id, max(value) max
from c group by id, e
Result:
id max
----- ---
5 210
2 500
4 600
5 380

Find rows in a table where field1 is the same and field 2 is different

I have rows of a table that stores a UserID, an EnrollmentID, and other data. I want to get all records where there is more than one occurrence of a UserID and EnrollmentID.
Sample data:
serial_no userID EnrollmentID
-------------------------------
1234 100 44
1235 100 55
1236 200 33
1237 300 66
1238 400 88
1239 400 77
I'd want the following rows returned:
1234 100 44
1235 100 55
1238 400 88
1239 400 77
EDIT: To clarify, I want all rows where the userid exists with different enrollment id's
SQL Server 2005 solution
select * from
(
select *, c = COUNT(*) over (partition by userID)
from sampletable
) sq
where c > 1
or more generically
select *
from sampletable
where userid in
(
select userid
from sampletable
group by userid
having COUNT(*) > 1
)
Using this sample
create table sampletable (serial_no int, userid int, enrollmentid int)
insert sampletable select 1234 ,100 ,44
insert sampletable select 1235 ,100 ,55
insert sampletable select 1236 ,200 ,33
insert sampletable select 1237 ,300 ,66
insert sampletable select 1238 ,400 ,88
insert sampletable select 1239 ,400 ,77
Output is
serial_no userid enrollmentid
1234 100 44
1235 100 55
1238 400 88
1239 400 77
select a.serial_no, a.userID, a.EnrollmentID
from a tableA
where a.userID in (
SELECT DISTINCT a.userID
FROM tableA a, tableA b
WHERE a.userID = b.userID
AND a.EnrollmentID <> b.EnrollmentID )
SELECT a.* FROM Table1 a
INNER JOIN (
SELECT UserID FROM Table1 GROUP BY UserID HAVING COUNT(*) > 1
) b ON a.UserID = b.UserID