SQL Server - Renumber in Order - sql-server-2008-r2

I have a table that I need to reorder a column, but I need to keep the original order by date.
TABLE_1
id num_seq DateTimeStamp
fb4e1683-7035-4895-b2c8-d084d9b42ce3 111 08-02-2005
e40e4c3e-65e4-47b7-b13a-79e8bce2d02d 114 10-07-2017
49e261a8-a855-4844-a0ac-37b313da2222 113 01-30-2010
6c4bffb7-a056-4a20-ae1c-5a31bdf683f2 112 04-15-2006
I want to reorder num_seq starting with 1001 through 1004 and keep the numbering in order. So 111 = 1001 and 112 = 1002 and so forth.
This is what I have so far:
DECLARE #num INT
SET #num = 0
UPDATE Table_1
SET #num = num_seq = #id + 1
GO
I know that UPDATE doesn't let me use the keyword ORDER BY. Is there a way to do this in SQL 2008 R2?

Stage the new num_seq in a CTE, then leverage that in your update statement:
declare #Table_1 table (id uniqueidentifier, num_seq int, DateTimeStamp datetime);
insert into #Table_1
values
('fb4e1683-7035-4895-b2c8-d084d9b42ce3', 111, '08-02-2005'),
('e40e4c3e-65e4-47b7-b13a-79e8bce2d02d', 114, '10-07-2017'),
('49e261a8-a855-4844-a0ac-37b313da2222', 113, '01-30-2010'),
('6c4bffb7-a056-4a20-ae1c-5a31bdf683f2', 112, '04-15-2006');
;with stage as
(
select *,
num_seq_new = 1000 + row_number()over(order by DateTimeStamp asc)
from #Table_1
)
update stage
set num_seq = num_seq_new;
select * from #Table_1
Returns:
id num_seq DateTimeStamp
FB4E1683-7035-4895-B2C8-D084D9B42CE3 1001 2005-08-02 00:00:00.000
E40E4C3E-65E4-47B7-B13A-79E8BCE2D02D 1004 2017-10-07 00:00:00.000
49E261A8-A855-4844-A0AC-37B313DA2222 1003 2010-01-30 00:00:00.000
6C4BFFB7-A056-4A20-AE1C-5A31BDF683F2 1002 2006-04-15 00:00:00.000

Related

Window Function For Consecutive Dates

I want to know how many users were active for 3 consecutive days on any given day.
e.g on 2022-11-03, 1 user (user_id = 111) was active 3 days in a row. Could someone please advise what kind of window function(?) would be needed?
This is my dataset:
user_id
active_date
111
2022-11-01
111
2022-11-02
111
2022-11-03
222
2022-11-01
333
2022-11-01
333
2022-11-09
333
2022-11-10
333
2022-11-11
If you are confident there are no duplicate user_id + active_date rows in the source data, then you can use two LAG functions like this:
SELECT user_id,
active_date,
CASE WHEN DATEADD(day, -1, active_date) = LAG(active_date, 1) OVER (PARTITION BY user_id ORDER BY active_date)
AND DATEADD(day, -2, active_date) = LAG(active_date, 2) OVER (PARTITION BY user_id ORDER BY active_date)
THEN 'Yes'
ELSE 'No'
END AS rowof3
FROM your_table
ORDER BY user_id, active_date;
If there might be duplication, use this FROM clause instead:
FROM (SELECT DISTINCT user_id, active_date :: DATE FROM your_table)

Unpivot in postgres with a column created in the same query

I am trying to unpivot a table with PostgreSQL as described here.
My problem is that I am creating a new column in my query which I want to use in my cross join lateral statement (which results in an SQL error because the original table does not have this column).
ORIGINAL QUESTION:
select
"Name",
case
when "Year"='2020' then "Date"
end as "Baseline"
from "test_table"
EDIT: I am using the example from the referred StackOverflow question:
create table customer_turnover
(
customer_id integer,
q1 integer,
q2 integer,
q3 integer,
q4 integer
);
INSERT INTO customer_turnover VALUES
(1, 100, 210, 203, 304);
INSERT INTO customer_turnover VALUES
(2, 150, 118, 422, 257);
INSERT INTO customer_turnover VALUES
(3, 220, 311, 271, 269);
INSERT INTO customer_turnover VALUES
(3, 320, 211, 171, 269);
select * from customer_turnover;
creates the following output
customer_id q1 q2 q3 q4
1 100 210 203 304
2 150 118 422 257
3 220 311 271 269
3 320 211 171 269
(I used the customer_id 3 twice because this column is not unique)
Essentially, what I would like to do is the following: I would like to calculate a new column qsum:
select customer_id, q1, q2, q3, q4,
q1+q2+q3+q4 as qsum
from customer_turnover
and use this additional column in my unpivoting statement to produce the following output:
customer_id turnover quarter
1 100 Q1
1 210 Q2
1 203 Q3
1 304 Q4
1 817 qsum
2 150 Q1
2 118 Q2
2 422 Q3
2 257 Q4
2 947 qsum
3 220 Q1
3 311 Q2
3 271 Q3
3 269 Q4
3 1071 qsum
3 320 Q1
3 211 Q2
3 171 Q3
3 269 Q4
3 971 qsum
As I do not want to have qsum in my final output, I understand that I cannot use it in my select statement, but even if I would use it like this
select customer_id, t.*, q1, q2, q3, q4,
q1+q2+q3+q4 as qsum
from customer_turnover c
cross join lateral (
values
(c.q1, 'Q1'),
(c.q2, 'Q2'),
(c.q3, 'Q3'),
(c.q4, 'Q4'),
(c.qsum, 'Qsum')
) as t(turnover, quarter)
I receive the following SQL error: ERROR: column c.qsum does not exist
How can I produce my desired output?
Not sure to well understand your issue, maybe a subquery can help :
select s.baseline
from
( select
"Name",
case
when "Year"='2020' then "Date"
end as "Baseline"
from "test_table"
) AS s

results mismatched when retrieved dates from column of type character varying

I have two tables,i want to get the min and max date stored in table1 cfrange column which is of type character varying.
table1 and table2 is mapped using sid. i want to get the max and min date range when compared with sid of table2.
table1:
sid cfrange
100 3390
101 8000
102 5/11/2010
103 11/12/2016
104 01/03/2016
105 4000
106 4000
107 03/12/2017
108 03/11/2016
109 4/04/2018
110 10/12/2016
table2:
sid description
102 success
103 success
104 Proceeding
107 success
108 success
I tried as below but its not giving the correct min and max value.Please advice.
select max(t1.cfrange),min(t1.cfrange) from table1 t1,table2 t2 where t1.sid=t2.sid;
You should join two tables and cast cfrange as a date and cross your fingers. (May be you must format it as a date before to cast it).
create table table1 (sid int, cfrange varchar(30));
insert into table1 values
(100, '3390'),
(101, '8000'),
(102, '5/11/2010'),
(103, '11/12/2016'),
(104, '01/03/2016'),
(105, '4000'),
(106, '4000'),
(107, '03/12/2017'),
(108, '03/11/2016'),
(109, '4/04/2018'),
(110, '10/12/2016');
create table table2 (sid int, description varchar(30));
insert into table2 values
(102, 'success'),
(103, 'success'),
(104, 'Proceeding'),
(107, 'success'),
(108, 'success');
select 'Min' as caption, min(cfrange) as value
from (select table1.sid, table1.cfrange::date
from table1
inner join table2
on table1.sid = table2.sid) tt
UNION ALL
select 'Max' as caption, max(cfrange) as value
from (select table1.sid, table1.cfrange::date
from table1
inner join table2
on table1.sid = table2.sid) tt;
caption | value
:------ | :---------
Min | 2010-11-05
Max | 2017-12-03
dbfiddle here

Get column of table for results having sum(a_int)=0 and order by date and group by another column

Think of a table like below:
unique_id
a_column
b_column
a_int
b_int
date_created
Let's say data is like:
-unique_id -a_column -b_column -a_int -b_int -date_created
1z23 abc 444 0 1 27.12.2016 18:03:00
2c31 abc 444 0 0 26.12.2016 13:40:00
2e22 qwe 333 0 1 28.12.2016 15:45:00
1b11 qwe 333 1 1 27.12.2016 19:00:00
3a33 rte 333 0 1 15.11.2016 11:00:00
4d44 rte 333 0 1 27.09.2016 18:00:00
6e66 irt 333 0 1 22.12.2016 13:00:00
7q77 aaa 555 1 0 27.12.2016 18:00:00
I want to get the unique_id s where b_int is 1, b_column is 333 and considering a_column, a_int column must always be 0, if there are any records with a_int = 1 even if there are records with a_int = 0 these records must not be shown in the result. Desired result is: " 3a33 , 6e66 " when grouped by a_column and ordered by date_created and got top1 for each unique a_column.
I tried lots of "with ties" and "over(partition by" samples, searched questions, but couldn't manage to do it. This is what I could do:
select unique_id
from the_table
where b_column = '333'
and b_int = 1
and a_column in (select a_column
from the_table
where b_column = '333'
and b_int = 1
group by a_column
having sum(a_int) = 0)
order by date_created desc;
This query returns the result like this " 3a33 ,4d44, 6e66 ". But I don't want "4d44".
You were on the right track with the partitions and window functions. This solution uses ROW_NUMBER to assign a value to the a_column so we can see where there is more than 1. The 1 is the most recent date_created. Then you select from the result set where the row_counter is 1.
;WITH CTE
AS (
SELECT unique_id
, a_column
, ROW_NUMBER() OVER (
PARTITION BY a_column ORDER BY date_created DESC
) AS row_counter --This assigns a 1 to the most recent date_created and partitions by a_column
FROM #test
WHERE a_column IN (
SELECT a_column
FROM #test
WHERE b_column = '333'
AND b_int = 1
GROUP BY a_column
HAVING MAX(a_int) < 1
)
)
SELECT unique_ID
FROM cte
WHERE row_counter = 1

TSQL Insert additional rows

What is the most efficient way to identify and insert rows for the following problem?
Here's my sample data
vId StartDate EndDate Distance
------------------------------------
256 2015-03-04 2015-03-05 365
271 2015-03-04 2015-03-04 86
315 2015-03-05 2015-03-06 254
256 2015-03-07 2015-03-09 150
458 2015-03-10 2015-03-12 141
458 2015-03-15 2015-03-17 85
315 2015-03-15 2015-03-16 76
I want to add additional rows for each vId where the StartDate <> EndDate like follows, so instead of just
315 2015-03-05 2015-03-06 254
256 2015-03-07 2015-03-09 150
I want to show the following
315 2015-03-05 2015-03-06 254
315 2015-03-06 2015-03-06 0
256 2015-03-07 2015-03-09 150
256 2015-03-08 2015-03-09 0
256 2015-03-09 2015-03-09 0
Thanks in advance.
Just a simple insert:
Insert Into Table(vId, StartDate, EndDate, Distance)
Select vId, DateAdd(dd, 1, StartDate), EndDate, 0
From TableName
Where StartDate <> EndDate
If you want just select but not insert then:
Select vId, StartDate, EndDate, Distance
From TableName
Union All
Select vId, DateAdd(dd, 1, StartDate), EndDate, 0
From TableName
Where StartDate <> EndDate
EDIT
This assumes that there are maximum 100 day difference. If you have longer intervals you can add more cross joins to increase possible values:
declare #t table(vId int, StartDate date, EndDate date, Distance int)
insert into #t values
(315, '2015-03-05', '2015-03-06', 254),
(256, '2015-03-07', '2015-03-09', 150)
;with cte as(select row_number() over(order by (select 1)) as rn
from (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t1(n)
cross join (values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) t2(n)
)
select * from #t
union all
select t1.vId, ca.StartDate, t1.EndDate, 0
from #t t1
cross apply(select dateadd(dd, c.rn, StartDate) as StartDate
from cte c
where dateadd(dd, c.rn, t1.StartDate) <= t1.EndDate) as ca
where t1.StartDate <> t1.EndDate
order by vId, StartDate
See fiddle http://sqlfiddle.com/#!6/9eecb/4641