SQL Select statement and show only changed - sql

I have the simple select script and it generates following audit table.
SELECT *
FROM Mytable
WHERE File = '123456A'
Output:
ID
File
StatusA
StatusB
User
UpdateDate
1
123456A
A
0
Tom
2021-01-01
12
123456A
B
0
Jack
2021-01-05
19
123456A
A
1
Alicia
2021-02-09
56
123456A
B
1
Jason
2021-03-09
87
123456A
A
1
Jason
2021-03-10
107
123456A
B
0
Ellie
2021-03-26
203
123456A
A
0
lucy
2021-04-08
239
123456A
B
1
Ellie
2021-04-16
I am trying to retrieve the rows when only column StatusB is changed. So it will generates the table like this.
SELECT *
FROM Mytable
WHERE File = '123456A'
-AND StatusB is changed
ID
File
StatusA
StatusB
User
UpdateDate
1
123456A
A
0
Tom
2021-01-01
19
123456A
A
1
Alicia
2021-02-09
107
123456A
B
0
Ellie
2021-03-26
239
123456A
B
1
Ellie
2021-04-16
In this case, I can see Alicia and Ellie changed the column StatusB. I am still thinking how to accomplish this goal.
Thanks,
-Ming

You can use lag():
select t.*
from (select t.*,
lag(statusB) over (order by updatedate) as prev_statusB
from Mytable t
where File = '123456A'
) t
where prev_statusB is null or prev_statusB <> statusB;

Related

How find duplicates of the same id but different date with SQL (Oracle)

I've got a datatable like that :
id
line
datedt
123
1
01/01/2021
123
2
01/01/2021
123
3
01/01/2021
777
1
13/04/2020
777
2
13/04/2020
123
1
12/04/2021
123
2
12/04/2021
888
1
01/07/2020
888
2
01/07/2020
452
1
05/01/2020
888
1
02/05/2021
888
2
02/05/2021
I'd like to obtain a result like that, ie : the nb of same id with differents dates.
Example we can find 123 with 2 diffents dates, 888 too, but only date for 777 and 452
id
nb
123
2
777
1
888
2
452
1
How could I get that ?
Hope it's clear :)
Thanks you
select id , count(distinct datedt) as nb
from table
group by id

SQL - Period range in subgroups of a group by

I have the following dataset:
A
B
C
1
John
2018-08-14
1
John
2018-08-20
1
John
2018-09-03
2
John
2018-11-13
2
John
2018-12-11
2
John
2018-12-12
1
John
2020-01-20
1
John
2020-01-21
3
John
2021-03-02
3
John
2021-03-03
1
John
2020-05-10
1
John
2020-05-12
And I would like to have the following result:
A
B
C
1
John
2018-08-14
2
John
2018-11-13
1
John
2020-01-20
3
John
2021-03-02
1
John
2020-05-10
If I group by A, B the 1st row and the third just concatenate which is coherent. How could I create another columns to still use a group by and have the result I want.
If you have another ideas than mine, please explain it !
I tried to use some first, last, rank, dense_rank without success.
Use lag(). Looks like B is a function of A in your data. So checking lag(A) will suffice.
select A,B,C
from (
select *, case when lag(A) over(order by C) = A then 0 else 1 end startFlag
from mytable
) t
where startFlag = 1
order by C

Exclude rows where keys match, but are on different rows

I'm looking for the best way to produce the result set in the scenario provided. My cust3 column isn't identifying the repeated values in the indvid2 column. The end result I'm looking for is to exclude the rows where key1 and key2 match (ids:1,2,6 and 7), then sum accounts where the acctids match.If there's a better way to code this, I welcome all suggestions. Thanks!
WITH T10 as (
SELECT acctid,invid,(
case
when invid like '%-R' then left (InvID,LEN(invid) -2) else InvID
END) as InvID2
FROM table x
GROUP BY acctID,invID
),
T11 as (
SELECT acctid, Invid2, COUNT(InvID2) as cust3
FROM T10
GROUP BY InvID2,acctid
HAVING
COUNT (InvID2) > 1
)
select DISTINCT
a.acctid,
a.name,
b.invid,
C.invid2,
D.cust3,
b.amt,
b.key1,
b.key2
from table a
inner join table b (nolock) on a.acctid = b.acctid
inner join T10 C (nolock) on b.invid = c.invid
inner join T11 D (nolock) on C.invid2 = D.invid2
Resultset
id acctID name invid invid2 Cust3 amt key1 key2
1 123 James 101 101 2 $500 NULL 6789
2 123 james 101-R 101 2 ($500) 6789 NULL
3 123 James 102 102 2 $350 NULL NULL
4 123 James 103 103 2 $200 NULL NULL
5 246 Tony 98-R 98 2 ($750) 7423 NULL
6 432 David 45 45 2 $100 NULL 9634
7 432 David 45-R 45 2 ($100) 9634 NULL
8 359 Stan 39-R 39 2 ($50) 6157 NULL
9 753 George 95 95 2 $365 NULL NULL
10 753 George 108 108 2 $100 NULL NULL
Desired Resultset
id acctID name invid invid2 Cust3 amt key1 key2
1 123 James 101 101 2 $500 NULL 6789
2 123 james 101-R 101 2 ($500) 6789 NULL
3 123 James 102 102 1 $350 NULL NULL
4 123 James 103 103 1 $200 NULL NULL
5 246 Tony 98-R 98 1 ($750) 7423 NULL
6 432 David 45 45 2 $100 NULL 9634
7 432 David 45-R 45 2 ($100) 9634 NULL
8 359 Stan 39-R 39 1 ($50) 6157 NULL
9 753 George 95 95 1 $365 NULL NULL
10 753 George 108 108 1 $100 NULL NULL
Then to sum amt by acctid
id acctid name amt
1 123 James $550
2 246 Tony ($750)
3 359 Stan ($50)
4 753 George $465
Something like:
;WITH Keys as (
SELECT Key1.acctID, [Key] = Key1.Key1
FROM YourTable as Key1
INNER JOIN YourTable as Key2
ON Key1.Key1 = Key2.Key2 and Key1.acctID = Key2.acctID
)
SELECT t.acctID, t.name, amt = SUM(t.amt)
FROM YourTable as t
LEFT JOIN Keys as k
ON t.acctID = k.acctID and (t.Key1 = [Key] or t.Key2 = [Key])
WHERE k.acctID is Null
GROUP BY t.acctID, t.name

Writing SQL INSERT which retrieves its data from two separate related rows

I am writing a SQL script that is to insert a new record using data from two rows that are under the same AccountID.
My table looks like the following:
AccountID | ActivityId | DisplayDetails | TransactionDate | EnvironmentId
============================================================================
1 7 Display1 2015-02-02 00:00:00.000 1
1 8 DisplayThis1 2018-02-02 00:00:00.000 1
1 7 Display2 1999-02-02 00:00:00.000 2
1 8 DisplayThis2 2000-02-02 00:00:00.000 2
My fix is to find find each 7,8 combination and insert a new row with ActivityId 78 that gets the DisplayDetails from ActivityId 7 and TransactionDate from ActivityId 8.
My queries looks like the following:
SELECT *
INTO #ActivityEight
FROM Account A
WHERE A.ActivityId = 8
INSERT INTO #Account (AccountId, ActivityId, DisplayDetails, TransactionDate)
SELECT VL.AccountId, 78, S.DisplayDetails, VL.TransactionDate
FROM #temp2 VL WITH(NOLOCK)
JOIN #ActivityEight S
ON VL.AccountId = S.AccountId
WHERE VL.ActivityId = 7
However when I run SELECT * FROM Account I get a 78 row for each 7 and 8 row, when I should only get 1 78 row per 7 and 8 combination.
AccountID | ActivityId | DisplayDetails | TransactionDate | EnvironmentId
=============================================================================
1 7 Display1 2015-02-02 00:00:00.000 1
1 8 DisplayThis1 2018-02-02 00:00:00.000 1
1 7 Display2 1999-02-02 00:00:00.000 2
1 8 DisplayThis2 2000-02-02 00:00:00.000 2
1 78 DisplayThis1 2015-02-02 00:00:00.000 NULL
1 78 DisplayThis2 2015-02-02 00:00:00.000 NULL
1 78 DisplayThis1 1999-02-02 00:00:00.000 NULL
1 78 DisplayThis2 1999-02-02 00:00:00.000 NULL
I believe I can utilize the EnvironmentId to achieve the desired functionality, but I'm not sure how.
Any help would be appreciated.
Thanks!
I think this will help you
INSERT INTO #Account (AccountId, ActivityId, DisplayDetails, TransactionDate)
SELECT VL.AccountId, 78, S.DisplayDetails, VL.TransactionDate
FROM Account VL WITH(NOLOCK)
JOIN Account S ON VL.AccountId = S.AccountId and VL.EnvironmentId = S.EnvironmentId
WHERE VL.ActivityId = 7 and S.ActivityId = 8

SQL Syntax to group this data in SQL Server 2012

I have a table (called StayDate) which looks like this:
ResaID Date RoomCategory RateAmount
1 2014-09-01 A 125
1 2014-09-02 A 125
1 2014-09-03 B 140
2 2014-09-04 A 125
2 2014-09-05 A 125
2 2014-09-06 A 125
2 2014-09-07 C 160
2 2014-09-08 C 160
The output from the SQL syntax I'm after need to look like this:
ResaID Count RoomCategory RateAmount
1 2 A 125
1 1 B 140
2 3 A 125
2 2 C 160
Can anyone help with the SQL syntax needed to summarize the data as above?
A way to do this without a GROUP BY:
SELECT DISTINCT ResaID, COUNT(*) OVER (PARTITION BY ResaID, RoomCategory, RateAmount) Count, RoomCategory, RateAmount
FROM StayDate