Excluding the data with two consecutive conditions in Sql - sql

I have a table looks like this.
Numbers No ZNo Place Year AId ABC
2 201905190611122 9208363 A/C/T/0/434 2019 4BBA17BB-01A9-41A6-BFA7-004CA0E6686F 1448
2 201802262493590 9208363 A/C/T/0/434 2018 4A895857-4E51-4ADC-836A-22D04E5D0B62 2008
1 20180119827875 9208364 A/C/T/0/435 2018 89BFD858-92AC-463B-91DF-54C22FDF7517 1150
1 20180119827875 9208365 A/C/T/0/436 2018 89BFD858-92AC-463B-91DF-54C22FDF7517 1150
2 201804273541023 9208366 A/C/T/0/437 2018 B01EFCA6-8397-4FA9-9EAD-13BE985D63DD 1348
2 201905197566364 9208366 A/C/T/0/437 2019 43E3D908-4AAD-4832-9981-115A5F9E9FC3 1466
2 201802084364285 9208367 A/C/T/0/438 2018 20BB4E90-6F59-484E-ADD3-5635F7CAACC3 1138
2 201802091458406 9208367 A/C/T/0/438 2018 E9085238-8437-4628-A125-09E5C811AB8D 1248
I want to write down a query that will first find same "Place" values. Then it will check out the "Year" columns. If the year values are the same for same place values, the data will be kept. So, it will basically should look like this:
Numbers No ZNo Place Year AId ABC
2 201802084364285 9208367 A/C/T/0/438 2018 20BB4E90-6F59-484E-ADD3-5635F7CAACC3 1138
2 201802091458406 9208367 A/C/T/0/438 2018 E9085238-8437-4628-A125-09E5C811AB8D 1248
Can you help me with this?

Have a derived table (the subquery) returning place/year combinations that exist at least twice. JOIN its result:
select t.*
from tablename t
join (select Place, Year
from tablename
group by Place, Year
having count(*) >= 2) dt
on t.place = dt.place and t.year = dt.year

You can use not exists :
select t.*
from table t
where not exists (select 1 from table t1 where t1.Place = t.Place and t1.year <> t.year);
By this way, you will also get A/C/T/0/435 & A/C/T/0/436 as because it doesn't have a other years too. So, you can add other unique column in sub-query. I found no is unique in sample data :
select t.*
from table t
where not exists (select 1
from table t1
where t1.Place = t.Place and t1.year <> t.year and t1.no <> t.no
);

You can use window functions:
select t.*
from (select t.*, count(*) over (partition by place, year) as cnt
from t
) t
where cnt >= 2;

Related

deleting specific duplicate and original entries in a table based on date

i have a table called "main" which has 4 columns, ID, name, DateID and Sign.
i want to create a query that will delete entries in this table if there is the same ID record in twice within a certain DateID.
i have my where clause that searches the previous 3 weeks
where DateID =((SELECT MAX( DateID)
WHERE DateID < ( SELECT MAX( DateID )-3))
e.g of my dataset im working with:
id
name
DateID
sign
12345
Paul
1915
Up
23658
Danny
1915
Down
37868
Jake
1916
Up
37542
Elle
1917
Up
12345
Paul
1917
Down
87456
John
1918
Up
78563
Luke
1919
Up
23658
Danny
1920
Up
in the case above, both entries for ID 12345 would need to be removed.
however the entries for ID 23658 would need to be kept as the DateID > 3
how would this be possible?
You can use window functions for this.
It's not quite clear, but it seems LAG and conditional COUNT should fit what you need.
DELETE t
FROM (
SELECT *,
CountWithinDate = COUNT(CASE WHEN t.PrevDate >= t.DateId - 3 THEN 1 END) OVER (PARTITION BY t.id)
FROM (
SELECT *,
PrevDate = LAG(t.DateID) OVER (PARTITION BY t.id ORDER BY t.DateID)
FROM YourTable t
) t
) t
WHERE CountWithinDate > 0;
db<>fiddle
Note that you do not need to re-join the table, you can delete directly from the t derived table.
Hope this works:
DELETE FROM test_tbl
WHERE id IN (
SELECT T1.id
FROM test_tbl T1
WHERE EXISTS (SELECT 1 FROM test_tbl T2 WHERE T1.id = T2.id AND ABS(T2.dateid - T1.dateid) < 3 AND T1.dateid <> T2.dateid)
)
In case you need more logic for data processing, I would suggest using Stored Procedure.

How can I use a Join from another table when im doing a Max to a column in ORACLE?

Getting This issue in which I'm using a Max to a Column, it returns me the number.
(My tables have already the Constraints).
Actual Return
CVEANO
CVENUMERO
CVEACCION
2021
7
4
2021
1
3
What I Want to Return from TblACCION
CVEANO
CVENUMERO
CVEACCION
CVEACCION NAME Brought from tblACCION
2021
7
4
NAME FOR NUMBER 4
2021
1
3
NAME FOR NUMBER 3
My actual Query is
SELECT
*
FROM
(
SELECT
cveano,
cvenumero,
max(cveaccion) as ultima
FROM
tblbitacoragf
WHERE
cveusuario = 1
GROUP BY
cvenumero,
cveano
order by max(fechaaccion) desc
)
WHERE ROWNUM <= 4
I've tried doing
INNER JOIN tblACCION ta USING (CVEACCION)
and in SELECT
ta.descripcion AS accion
but I guess there's something wrong, because it always asks me for
00000 - "missing right parenthesis"
and I did check for parenthesis, but there's no lack of parenthesis.
UPDATE
I've tried this 2.0 , nothing
As I understood, you are looking for something like this.
SELECT
*
FROM
(
SELECT
t1.cveano,
t1.cvenumero,
max(t1.cveaccion) as ultima,
max(t2.cveaccionName) as cveaccionName
FROM
tblbitacoragf t1
INNER JOIN tblACCION t2 ON t1.cveaccion = t2.cveaccion
WHERE
t1.cveusuario = 1
GROUP BY
t1.cvenumero,
t1.cveano
order by
max(t1.fechaaccion) desc
)
WHERE
ROWNUM <= 4
Also you can try this.
SELECT
abc.*,
xyz.cveaccionName
FROM
(
SELECT
cveano,
cvenumero,
max(cveaccion) as ultima
FROM
tblbitacoragf
WHERE
cveusuario = 1
GROUP BY
cvenumero,
cveano
order by
max(fechaaccion) desc
) abc
INNER JOIN tblACCION xyz ON abc.ultima = xyz.cveaccion
WHERE
ROWNUM <= 4

Using self join to find duplicates in SQL

I know that there are other questions like this. However, my question is about why the query that I am using is not returning the optimal results. Below is the query. To give context, I have a single table that has 113 columns/fields. However, only 4 really matter; acct, year, qtr, cnty (county). This table is a list of employers by establishment. An employer can appear more than once. The same person owning 12 starbucks being the best example. What I am looking for is a query that will show when acct values have different cnty values. The below query works without error but it shows far too much. It shows rows where the acct value is the same but the cnty value is the same as well. Any thoughts on looking at this query as to why it shows too much?
select distinct t1.acct, t1.year, t1.qtr, t1.cnty
from dbo.table t1 join dbo.table t2 on t1.acct=t2.acct
where (t1.cnty <> t2.cnty)
order by t1.acct, t1.year, t1.qtr, t1.cnty
Intended result
acct year qtr cnty
1234567777 2007 4 7
1234567777 2008 1 9
1234567890 2006 4 31
1234567890 2007 1 3
2345678901 2006 4 7
2345678901 2007 2 1
Is this what you want?
select distinct t.acct, t.year, t.qtr, t.cnty
from (select t.*, min(cnty) over (partition by acct, year, qtr) as min_cnty,
max(cnty) over (partition by acct, year, qtr) as max_cnty
from dbo.table t
) t
where min_cnty <> max_cnty;

SQL query - Difference between the values from two rows and two columns

I am struggling to get this working, using T-SQL Query (SQL SERVER 2008) for the following problem:
Ky ProductID Start # End # Diff
1 100 10 12 0
2 100 14 20 2 (14 - 12)
3 100 21 25 1 (21 - 20)
4 100 30 33 5 (30 - 25)
1 110 6 16 0
2 110 20 21 4 (20 - 16)
3 110 22 38 1 (22 - 21)
as you can see I need the difference between values in two different rows and two columns.
I tried
with t1
( select ROW_NUMBER() OVER (PARTITION by ProductID ORDER BY ProductID, Start# ) as KY
, productid
, start#
, end#
from mytable)
and
select DATEDIFF(ss, T2.complete_dm, T1.start_dm)
, <Keeping it simple not including all the columns which I selected..>
FROM T1 as T2
RIGHT OUTER JOIN T1 on T2.Ky + 1 = T1.KY
and T1.ProductID = T2.ProductID
The problem with the above query is when the productID changes from 100 to 110 still it calculates the difference.
Any help in modifying the query or any simpler solution much appreciated.
Thanks
You can try below code for the required result :
select ky,Start,[End],(select [end] from table1 tt where (tt.ky)=(t.ky-1) and tt.ProductID=t.ProductID) [End_Prev_Row],
case ky when 1 then 0
else (t.start -(select [end] from table1 tt where (tt.ky)=(t.ky-1) and tt.ProductID=t.ProductID))
end as Diff
from table1 t
SQL FIDDLE
Try something like that. It should give you the difference you want. I'm getting the first row for each product in the first part and then recursively build up by using the next Ky.
with t1
as
(
select ProductID, Ky, 0 as Difference, [End#]
from mytable where ky = 1
union all
select m.ProductID, m.Ky, m.[Start#] - t1.[End#] as Difference, m.[End#]
from mytable m
inner join t1 on m.ProductID = t1.ProductID and m.Ky = t1.Ky + 1
)
select Ky, ProductID, Difference from t1
order by ProductID, Ky
As Anup has mentioned, your query seems to be working fine, I just removed DateDiff to calculate the difference, as I assume columns are not of DATE datatype from your example, I guess that was the issue, please find below the modified query
with t1
as
( select ROW_NUMBER() OVER (PARTITION by ProductID ORDER BY ProductID ) as KY
, productid
, st
, ed
from YourTable)
select T1.ProductID, t1.ST,t1.ED, ISNULL(T1.st - T2.ed,0) as Diff
FROM T1 as T2
RIGHT OUTER JOIN T1 on T2.KY+1 = T1.KY
and T1.ProductID = T2.ProductID
SELECT ROW_NUMBER() OVER (PARTITION by rc.ContractID ORDER BY rc.ID) AS ROWID,rc.ID,rc2.ID,rc.ContractID,rc2.ContractID,rc.ToDate,rc2.FromDate
FROM tbl_RenewContracts rc
LEFT OUTER JOIN tbl_RenewContracts rc2
ON rc2.ID = (SELECT MAX(ID) FROM tbl_RenewContracts rcs WHERE rcs.ID < rc.ID AND rcs.ContractID = rc.ContractID)
ORDER BY rc.ContractID
Replace your table name and columns and add calculated column to get the DATEDIFF.

SQL select row-wise increase in amount of running total column

Suppose I have a table with columns (DayId, RunningTotal):
DayId RunningTotal
---------------------
1 25
3 50
6 100
9 200
10 250
How can I select the DayId and the amount the RunningTotal has increased from the previous day? i.e. how can I select:
DayId DayTotal
---------------------
1 25
3 25
6 50
9 100
10 50
The only current method I know is with a while loop I am trying to factor out. Also, the DayId has no regular rules, just that it is some increasing integer value, but it increases by an irregular amount as shown in the example table.
EDIT: using MS SQL Server 2005
with cte as (
select dayid, runningtotal, row_number() over (order by dayid asc) as row_index
from #the_table
)
select cur.dayid, cur.runningtotal - coalesce(prev.runningtotal, 0) as daytotal
from cte cur
left join cte prev on prev.row_index = cur.row_index - 1
(I really wish they'd implemented support for the lead and lag functions in SQL Server :|)
There is probably a more succinct way than this, but try:
select t3.DayId,
case when t4.DayId is null then t3.RunningTotal else t3.RunningTotal - t4.RunningTotal end as DayTotal
from (
select t1.DayId, max(t2.DayId) as PreviousDayId as
from MyTable t1
left outer join MyTable t2 on t2.DayId < t1.DayId
group by t1.DayId
) a
inner join MyTable t3 on a.DayId = t3.DayId
left outer join MyTable t4 on a.PreviousDayId = t4.DayId