SQL Server show non matching records - sql

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)
)

Related

Apply Sequence based on unique_id

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.

Delete Duplicate rows from table which have same Id

I have a table Emp which have records like this
Id Name
1 A
2 B
3 C
1 A
1 A
2 B
3 C
Now I want to delete the duplicate rows from the table
I am using this query to select or count number of duplicate records
SELECT NameCol, COUNT(*) as TotalCount FROM TestTable
GROUP BY NameCol HAVING COUNT(*) > 1
ORDER BY COUNT(*) DESC
and what query should i write to delete the duplicate rows from table.
if I write this query to delete the duplicate records then it is giving a (0) row Affected result.
`DELETE FROM TestTable
WHERE ID NOT IN ( SELECT MAX(ID) FROM
TestTable
GROUP BY NameCol
)`
For sqlserver 2005+
Testdata:
declare #t table(Id int, Name char(1))
insert #t values
(1,'A'),(2,'B'),(3,'C'),(1,'A'),(1,'A'),(2,'B'),(3,'C')
Delete statement(replace #t with your Emp table)
;with a as
(
select row_number() over (partition by id, name order by id) rn
from #t
)
delete from a where rn > 1
select * from #t
**Q How to Remove duplicate data with help of Rowid**
create table abcd(id number(10),name varchar2(20))
insert into abcd values(1,'abc')
insert into abcd values(2,'pqr')
insert into abcd values(3,'xyz')
insert into abcd values(1,'abc')
insert into abcd values(2,'pqr')
insert into abcd values(3,'xyz')
select * from abcd
id Name
1 abc
2 pqr
3 xyz
1 abc
2 pqr
3 xyz
Delete Duplicate record but keep Distinct Record in table
DELETE
FROM abcd a
WHERE ROWID > (SELECT MIN(ROWID) FROM abcd b
WHERE b.id=a.id
);
run the above query 3 rows delete
select * from abcd
id Name
1 abc
2 pqr
3 xyz

How to select multi record depending on some column's condition?

Say there is a SQL Server table which contain 2 columns: ID, Value
The sample data looks like this:
ID value
------------------
1 30
1 30
2 50
2 50
3 50
When I run this query:
select ID, NEWID(), value
from table1
order by ID
The result looks like this:
1 30 E152AD19-9920-4567-87FF-C4822FD9E485
1 30 54F28C58-ABA9-4DFB-9A80-CE9C4C390CBB
2 50 ........
2 50 ........
3 50 4E5A9E26-FEEC-4CC7-9AC5-96747053B6B2
But what I want is : how many record of ID depending on (sum of value /30 )'s result, for example of ID 2, it's value's sum is 50+50=100, and 100/30=3, so ID 2 will display in query result three times
The final result i want is like this:
1 E152AD19-9920-4567-87FF-C4822FD9E485
1 54F28C58-ABA9-4DFB-9A80-CE9C4C390CBB
2 4E5A9E26-FEEC-4CC7-9AC5-96747053B6B2
2 ....
2 ....
3 D861563E-E01A-4198-9E92-7BEB4678E5D1
Please note ID of 2 display three times, wait for your helps, thanks.
How about something like
CREATE TABLE Table1
([ID] int, [value] int)
;
INSERT INTO Table1
([ID], [value])
VALUES
(1, 30),
(1, 30),
(2, 50),
(2, 50),
(3, 50)
;
;WITH SummedVals AS (
SELECT ID,
SUM(value) / 30 Cnt
FROM Table1
GROUP BY ID
)
, Vals AS (
SELECT ID,
Cnt - 1 Cnt
FROM SummedVals
UNION ALL
SELECT ID,
Cnt - 1 Cnt
FROM Vals
WHERE Cnt > 0
)
SELECT ID,
NEWID()
FROM Vals
ORDER BY 1
SQL Fiddle DEMO

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

Order by specific values in a column without using case statement

I would like to get the records in the below format:
if i have a record like
A, B, C, D
and I would like get record in this order -
B, A, C, D, E, F, G, H, so on,
But I need the value B should be at the first row...
try this:
SELECT
*, 1 AS SortBy
FROM YourTable
WHERE YourCol='B'
UNION ALL
SELECT
*, 2 AS SortBy
FROM YourTable
WHERE YourCol!='B'
ORDER BY SortBy, YourCol
You don't give any reason to not want to use CASE. I'd still give it a try and see which is faster, the UNION ALL or the CASE method:
SELECT
*
FROM YourTable
ORDER BY CASE WHEN YourCol='B' then 1 ELSE 2 END, YourCol
EDIT Working example:
DECLARE #YourTable table (YourCol char(1), RowValue varchar(5))
INSERT #YourTable VALUES ('A','aaa')
INSERT #YourTable VALUES ('A','aa')
INSERT #YourTable VALUES ('B','bbb')
INSERT #YourTable VALUES ('B','bb')
INSERT #YourTable VALUES ('C','ccc')
INSERT #YourTable VALUES ('D','ddd')
INSERT #YourTable VALUES ('E','eee')
INSERT #YourTable VALUES ('F','fff')
SELECT
*, 1 AS SortBy
FROM #YourTable
WHERE YourCol='B'
UNION ALL
SELECT
*, 2 AS SortBy
FROM #YourTable
WHERE YourCol!='B'
ORDER BY SortBy, YourCol
OUTPUT:
YourCol RowValue SortBy
------- -------- -----------
B bbb 1
B bb 1
A aaa 2
A aa 2
C ccc 2
D ddd 2
E eee 2
F fff 2
(8 row(s) affected)
SELECT * from mytable where mycolumn = "B";
followed by
SELECT * from mytable where mycolumn != "B" order by mycolumn asc;
Declare and populate table:
DECLARE #t TABLE (col1 CHAR)
INSERT #t
SELECT char(number+ 65)
FROM master..spt_values
WHERE type = 'P' AND number < 6
Query1:
SELECT *, cast(ascii(col1)-66 as bit) * 2 + ascii(col1) [orderby]
FROM #t
ORDER BY cast(ascii(col1)-66 as bit) * 2 + ascii(col1)
Query2:
SELECT *
FROM #t
ORDER BY replace(col1, 'B', ' ')
Result for Query1: (the [orderby] column is included for documentation only)
col1 orderby
---- --------
B 66
A 67
C 69
D 70
E 71
F 72