how to do partitioning on VARCHAR column - sql

DECLARE #Table1 TABLE
(ID int, STATUS varchar(1))
;
INSERT INTO #Table1
(ID, STATUS)
VALUES
(1, 'A'),
(1, 'A'),
(1, 'A'),
(1, 'B'),
(1, 'A'),
(2, 'C'),
(2, 'C')
;
Script :
Select *,ROW_NUMBER()OVER(PARTITION BY STATUS ORDER BY (SELECT NULL))RN from #Table1
Getting Result Set
ID STATUS RN
1 A 1
1 A 2
1 A 3
1 A 4
1 B 1
2 C 1
2 C 2
Need Output
ID STATUS RN
1 A 1
1 A 2
1 A 3
1 B 1
1 A 1
2 C 1
2 C 2

Try this
DECLARE #Table1 TABLE
(ID int, STATUS varchar(1));
INSERT INTO #Table1
(ID, STATUS)
VALUES
(1, 'A'),
(1, 'A'),
(1, 'A'),
(1, 'B'),
(1, 'A'),
(2, 'C'),
(2, 'C');
;WITH Tmp
AS
(
SELECT *, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS RowNumber FROM #Table1
)
SELECT
A.ID ,
A.STATUS ,
ROW_NUMBER() OVER (PARTITION BY A.STATUS, (A.RowNumber - A.RN) ORDER BY (SELECT NULL)) AS RN
FROM
(
Select *, ROW_NUMBER() OVER(PARTITION BY STATUS ORDER BY RowNumber) AS RN from tmp
) A
ORDER BY
A.RowNumber
Output:
ID STATUS RN
----------- ------ ------
1 A 1
1 A 2
1 A 3
1 B 1
1 A 1
2 C 1
2 C 2

Firstly, In the insert statement that you posted. How is 4 different from 1,2 and 3, if it is based on a different column then include that column as well in "row_number" in partition by sub clause. Because otherwise it will think that 'A' in 4 and 'A' in 1,2,3 are same and therefore group them together.
INSERT INTO #Table1
(ID, STATUS)
VALUES
(1, 'A'), <-- 1
(1, 'A'), <-- 2
(1, 'A'), <-- 3
(1, 'B'),
(1, 'A'), <-- 4
(2, 'C'),
(2, 'C')
;

Related

Pivot and Sum in Amazon Redshift

I have a following tables
table1
id name
1 A
3 B
table2
id label value
1 tag a
1 tag b
1 time 10
1 time 20
1 score 20
2 tag a
2 time 30
2 score 40
3 tag b
3 time 50
3 time 55
3 score 60
first I'd like to join table2 as follows
select *
from table1 left join on table2 using(id)
where label in ('tag')
id name tag
1 A a
1 A b
3 B b
and then join table2 with id and pivot and sum up them
id name tag time score
1 A a 10 20
1 A b 10 20
3 B b 50 60
I guess it is very complicated, are there any way to achieve this?
In Redshift it seems that there is no way to pivot them.
Thanks.
This looks to be a pivot query. I think this does what you are looking for:
create table table1 (id int, name varchar(16));
insert into table1 values
(1, 'A'),
(3, 'B')
;
create table table2 (id int, label varchar(16), value varchar(16));
insert into table2 values
(1, 'tag', 'a'),
(1, 'tag', 'b'),
(1, 'time', '10'),
(1, 'score', '20'),
(2, 'tag', 'a'),
(2, 'time', '30'),
(2, 'score', '40'),
(3, 'tag', 'b'),
(3, 'time', '50'),
(3, 'score', '60')
;
select t2.id, a.name, a.tag_value, sum(decode(label, 'time', value::int)) as total_time, sum(decode(label, 'score', value::int)) as total_score
from table2 t2
join (
select id, name, value as tag_value
from table1 t1 left join table2 t2 using(id)
where t2.label in ('tag')
) a
on t2.id = a.id
group by 1, 2, 3
order by 1, 2, 3
;

Violation on primary key with multiple keys in table

CREATE TABLE parameters (
tag_id BIGINT,
id NVARCHAR(255),
idx NVARCHAR(255),
primary key (tag_id, idx)
);
CREATE TABLE tag
([oid] int, [Name] varchar(1))
;
INSERT INTO tag
([oid], [Name])
VALUES
(1, 'A'),
(2, 'B'),
(3, 'C'),
(4, 'D')
;
INSERT parameters (tag_id, id, idx)
SELECT tag.oid, id.a, idx.a
FROM
( VALUES (1), (0), ('A'), (2) ) AS id(a),
( VALUES ('a'), ('b'), ('c'), ('d') ) AS idx(a),
tag
This should be output:
tag_id id idx
______________________________________________
1 1 a
1 0 b
1 A c
1 2 d
2 1 a
2 0 b
2 A c
2 2 d
3 1 a
3 0 b
3 A c
3 2 d
4 1 a
4 0 b
4 A c
4 2 d
Below is the error which I am getting:
Cannot insert duplicate key in object 'tag_parameters'. The duplicate
key value is (1, a).
Why if I have only one combination (1, a). The next one is (2, a).
You can use same column idx in single values construct :
SELECT t.oid, a.id, a.idx
FROM tag t CROSS JOIN
( VALUES ('1', 'a'), ('0', 'b'), ('A', 'c'), ('2', 'd')
) AS a(id, idx);

Count Number of Consecutive Occurrence of values in Table with new partition count although repeated rows

create table #t_Jenas (Id int, Name char)
insert into #t_Jenas values
(1, 'A'),
(2, 'A'),
(3, 'B'),
(4, 'B'),
(5, 'B'),
(6, 'B'),
(7, 'C'),
(8, 'B'),
(9, 'B')
for row number partition by, if repeated rows, the number will continue that makes the minus column is not ascending. any idea how to make the partition number starts from 1 although repeat rows as data above?
select name,row_number() over (order by id) as cont ,row_number() over (partition by name order by id) as newcount,( row_number() over (order by id)-row_number() over (partition by name order by id)) as rowminusnewcount --, count(*) as cnt
from #t_Jenas
Actual:
name cont newcount rowminusnewcount
A 1 1 0
A 2 2 0
B 3 1 2
B 4 2 2
B 5 3 2
B 6 4 2
C 7 1 6
B 8 5 3
B 9 6 3
Expected:
name cont newcount rowminusnewcount
A 1 1 0
A 2 2 0
B 3 1 2
B 4 2 2
B 5 3 2
B 6 4 2
C 7 1 6
B 8 1 7
B 9 2 7
I figured out the meaning of the last column:
select name, id,
row_number() over (partition by grp, name order by id) as new_count,
count(*) over (order by min_grp_id) - count(*) over (partition by grp, name)
from (select t.*, min(id) over (partition by grp, name) as min_grp_id
from (select t.*,
(row_number() over (order by id) - row_number() over (partition by name order by id)
) as grp
from t_Jenas t
) t
) t
order by id;
Here is a db<>fiddle.
My guess is cont, newcount and rowminusnewcount all are row_numbers. I modified id to show the idea.
create table #t_Jenas (Id int, Name char);
insert into #t_Jenas values
(10, 'A'),
(20, 'A'),
(30, 'B'),
(40, 'B'),
(50, 'B'),
(60, 'B'),
(70, 'C'),
(80, 'B'),
(90, 'B');
select name, cont,
row_number() over (partition by grp, name order by id) as new_count,
cont - row_number() over (partition by grp, name order by id) rowminusnewcount
from (
select t.*, row_number() over (order by id) as cont
, row_number() over (order by id) - row_number() over (partition by name order by id) as grp
from #t_Jenas t
) t
order by id
Result
name cont new_count rowminusnewcount
A 1 1 0
A 2 2 0
B 3 1 2
B 4 2 2
B 5 3 2
B 6 4 2
C 7 1 6
B 8 1 7
B 9 2 7

Update OrderID based on the Select Order By Results?

I am using SQLite 3. I have a table MyTable, as follows:
Create table mytable (ID as INTEGER, OrderID as INTEGER, a as INTGER, b as INTEGER);
Insert into mytable (ID, OrderID,a,b) values (1, 1,1,1);
Insert into mytable (ID, OrderID,a,b) values (1, 2,1,2);
Insert into mytable (ID, OrderID,a,b) values (2, 1,1,3);
Insert into mytable (ID, OrderID,a,b) values (2, 3,2,1);
Insert into mytable (ID, OrderID,a,b) values (3, 1,2,3);
Now if I using the following statement:
Select * from mytable ORDER BY a desc, b desc;
I will get all rows in a different order, as follows:
(3, 1, 2, 3);
(2, 3, 2, 1);
(2, 1, 1, 3);
(1, 2, 1, 2);
(1, 1, 1, 1);
Now I want to update the order ID to the sequence number of the rows appear in the above results, as follows:
(3, 1, 2, 3);
(2, 2, 2, 1);
(2, 3, 1, 3);
(1, 4, 1, 2);
(1, 5, 1, 1);
How to do so?
Try This :-
Select ROW_NUMBER() OVER (ORDER BY (SELECT 1 ) ) AS ordNo, * INTO #TempTable from
mytable ORDER BY a desc, b desc;
UPDATE mytable SET OrderID = ordNo FROM #TempTable WHERE mytable.ID
=#TempTable.ID AND mytable.a=#TempTable.a AND mytable.b=#TempTable.b
Assuming that the a and b values are unique:
update mytable t
set orderid = (select count(*)
from mytable t2
where t2.a > t.a or
(t2.a = t.a and t2.b >= t.b)
);
There is a column [rowid][1] responsible for every rowid
Most tables in a typical SQLite database schema are rowid tables.
Rowid tables are distinguished by the fact that they all have a unique, non-NULL, signed 64-bit integer rowid that is used as the access key for the data in the underlying B-tree storage engine.
Due to old SQLite version didn't support ROW_NUMBER window function, you can use a subquery in select to make it.
You can try to use correlated subquery and UPDATE by rowid.
Schema (SQLite v3.18)
Create table mytable (ID INT, OrderID INT, a INT, b INT);
Insert into mytable (ID, OrderID,a,b) values (1, 1,1,1);
Insert into mytable (ID, OrderID,a,b) values (1, 2,1,2);
Insert into mytable (ID, OrderID,a,b) values (2, 1,1,3);
Insert into mytable (ID, OrderID,a,b) values (2, 3,2,1);
Insert into mytable (ID, OrderID,a,b) values (3, 1,2,3);
update mytable
set orderid=
(
SELECT (select count(*)
from mytable tt
where tt.a > t1.a or
(tt.a = t1.a and tt.b >= t1.b)) rn
FROM mytable t1
where mytable.rowid=t1.rowid
);
Query #1
SELECT * FROM mytable order by OrderID;
| ID | OrderID | a | b |
| --- | ------- | --- | --- |
| 3 | 1 | 2 | 3 |
| 2 | 2 | 2 | 1 |
| 2 | 3 | 1 | 3 |
| 1 | 4 | 1 | 2 |
| 1 | 5 | 1 | 1 |
View on DB Fiddle

Delete duplicate in sql based on other column value

I want to remove duplicates based on below condition.
My table contains data like cross relation. Column 1 value exist in column 2 and vice versa.
sample table
id id1
-------------
1 2
2 1
3 4
4 3
5 6
6 5
7 8
8 7
I want to delete 1 row from first two rows, same from third and forth, same for fifth and sixth and so on..
Can anyone please help?
Like this way you are going to delete just the second row from each group of 2 rows:
CREATE TABLE [LIST_ID](
[ID] [NUMERIC](4, 0) NOT NULL,
[ID_1] [NUMERIC](4, 0) NOT NULL
);
INSERT INTO LIST_ID (ID, ID_1)
VALUES
(1, 2),
(2, 1),
(3, 4),
(4, 3),
(5, 6),
(6, 5);
WITH First_Row AS
(
SELECT ROW_NUMBER() OVER (ORDER BY ID ASC) AS Row_Number, *
FROM LIST_ID
)
DELETE FROM First_Row WHERE Row_Number % 2 ='0';
SELECT * FROM LIST_ID;
How about this:
DELETE
FROM myTable
WHERE id IN (
SELECT CASE WHEN id < id1 THEN id ELSE id1 END
FROM myTable
)
Where myTable is the sample table with data.
declare #t table (id1 int, id2 int)
insert into #t (id1, id2)
values
(1, 2),
(2, 1),
(2, 1),
(2, 1),
(3, 4),
(3, 4),
(5, 6),
(7, 8),
(7, 6),
(6, 7),
(5, 0)
delete t2
from #t t1
inner join #t t2 on t2.id1 = t1.id2 and t2.id2 = t1.id1
where t2.id1 > t1.id1
select * from #t order by 1, 2
declare #t table (id1 int, id2 int)
insert into #t (id1, id2)
values
(1, 2),
(2, 1),
(3, 4),
(4, 3),
(5, 6),
(6, 5),
(7, 8),
(8, 7)
;
;with a as (
select
row_number() over (order by id1) rn
,t.id1
,t.id2
from
#t t
)
delete t from
#t t
join (
select
a.id1
,a.id2
from
a a
where
exists(
select
*
from
a b
where
a.id2 = b.id1 and a.id1 = b.id2 and a.rn > b.rn
)
) c on t.id1 = c.id1 and t.id2 = c.id2
;
select * from #t;
/* OUTPUT
id1 id2
1 2
3 4
5 6
7 8
*/
It'll vary a little based on which row you want to keep, but if you really have simple duplicates as in your example, and every pair exists in both orders, this should do it:
DELETE FROM MyTable
WHERE ID > ID1
So what i could understand you want to delete the rows from table where id = id1.
delete from TableA as a
where exists(select 1 from TableA as b where a.id = b.id1)