Distinct records based on some columns in SQL - sql

I have a table named myTable in SQL server database. Let`s say the name of columns is like:
col1, col2, col3, col4, col5
There are thousands of records in the table.
I want to select records with no repetition based on only 4 columns.
currently I use the following query:
SELECT DISTINCT col1, col2, col3, col4 FROM myTable
The query does return unique and distinct records, however I need to have col5 in the result too, even thought I do not want to col5 to be considered when I distinct records.
for example, there are three records in the table as follows:
col1 col2 col3 col4 col5
1 2 3 4 5
2 5 6 9 7
1 2 3 4 10
I want the result to be something like this:
col1 col2 col3 col4 col5
1 2 3 4 5
1 2 3 4 10

That will give you the records you like but only col1 to col4:
SELECT col1, col2, col3, col4
FROM myTable
group by col1, col2, col3, col4
having count(*) > 1
If you also need col5 then use
select t1.*
from myTable t1
join
(
SELECT col1, col2, col3, col4
FROM myTable
group by col1, col2, col3, col4
having count(*) > 1
) t2 on t1.col1 = t2.col1
and t1.col2 = t2.col2
and t1.col3 = t2.col3
and t1.col4 = t2.col4
Edit
After you edited your question, this is the answer:
SELECT col1, col2, col3, col4, min(col5) as col5
FROM myTable
group by col1, col2, col3, col4

Related

Get columns from another column

I have the following table :
ColID Columns
1 SELECT Col1, Col2, Col3, Col4, Col5 FROM MyTab
I want to get the column names between SELECT and FROM.
CREATE TABLE dbo.Mytab(ColID int, Columns varchar(max))
INSERT INTO dbo.Mytab(ColID,Columns)
VALUES(1,'SELECT Col1, Col2, Col3, Col4, Col5 FROM MyTab')
GO
SELECT SUBSTRING(Columns, CHARINDEX('SELECT', Columns) +6
, CHARINDEX('FROM',Columns) - CHARINDEX('SELECT', Columns) - Len('FROM')-2)
FROM dbo.Mytab
| (No column name) |
| :----------------------------- |
| Col1, Col2, Col3, Col4, Col5 |
db<>fiddle here
If this is a query that you need the columns for, you can get them with dm_exec_describe_first_result_set:
select name from sys.dm_exec_describe_first_result_set ( #myQuery, #parameters, 0)
If it is just a table, you can use sys.columns:
select name from sys.columns where object_id = object_id('dbo.myTable')
To get it as a nice table I improved(think so :-) ) the fiddle above
Setup:
CREATE TABLE dbo.Mytab(ColID int, Columns varchar(max))
INSERT INTO dbo.Mytab(ColID,Columns)
VALUES(1,'SELECT Col1, Col2, Col3, Col4, Col5 FROM MyTab');
INSERT INTO dbo.Mytab(ColID,Columns)
VALUES(2,'SELECT Col3, Col4, Col5, Col6 FROM MyTab')
Query:
select m.colid, p.value from dbo.myTab m CROSS APPLY string_split((SELECT SUBSTRING(m.Columns, CHARINDEX('SELECT',m.Columns) +6
, CHARINDEX('FROM',m.Columns) - CHARINDEX('SELECT', m.Columns) - Len('FROM')-2) ) ,',') as p
Result:
colid
value
1
Col1
1
Col2
1
Col3
1
Col4
1
Col5
2
Col3
2
Col4
2
Col5
2
Col6

I have a unique or distinct recors in all the column, table

I need a unique record all the table and all the column how can I get
Table1
Col1 col2 col3 col4 col5
A. P. 20. 21
B. Q. 18. 19
C. R 17. 16
Table2
Col1 col2 col3 col4 col5
A. P. 51 58
B. Q. 60 65
C. R 18 25
D. S. 33. 31
Table3
Col1 col2 col3 col4 col5
A. P. 60. 13
B. Q. 75 61
E t 100 108
F. U. 91. 98
Output of table (I need like dz output)
Col1 col2 col3 col4 col5
A. P. 20. 21
B. Q. 18. 19
C. R 17. 16
D. S. 33. 31
E. T. 100 108
F. U. 91. 98
To get all the unique rows you can combine all the records from all three tables using union all and use distinct to get unique rows.
select distinct col2 ,col3 ,col4 ,col5 from (
select col2 ,col3 ,col4 ,col5 from Table1
union all
select col2 ,col3 ,col4 ,col5 from Table2
union all
select col2 ,col3 ,col4 ,col5 from Table3 )T
Or if you wan to show first record of each unique col1 and col2 value as in your output table use below query (I didn't use Col1 in the query since it's serial number for that table only):
with cte as (
select row_number() over (partition by Col2,Col3 order by sl)rn, col2 ,col3 ,col4 ,col5 from (
select 1 sl, col2 ,col3 ,col4 ,col5 from Table1
union all
select 2 sl, col2 ,col3 ,col4 ,col5 from Table2
union all
select 3 sl ,col2 ,col3 ,col4 ,col5 from Table3 )T
)select row_number() over (order by col1),Col1,Col2, Col3, Col4 from cte where rn=1
You seem to want the first result based on the first two columns. One method uses union all:
select col1, col2, col3, col4
from table1
union all
select col1, col2, col3, col4
from table2 t2
where not exists (select 1 from table1 t1 where t1.col1 = t2.col1 and t1.col2 = t2.col2)
union all
select col1, col2, col3, col4
from table3 t3
where not exists (select 1 from table1 t1 where t1.col1 = t3.col1 and t1.col2 = t3.col2) and
not exists (select 1 from table2 t2 where t2.col1 = t3.col1 and t2.col2 = t3.col2) ;
You can also do this with row_number():
select col1, col2, col3, col4k
from (select t.*,
row_number() over (partition by col1, col2 order by which) as seqnum
from ((select 1 as which, col1, col2, col3, col4
from table1
) union all
(select 2 as which, col1, col2, col3, col4
from table2
) union all
(select 3 as which, col1, col2, col3, col4
from table3
)
) t
) t
where seqnum = 1;
With an index on (col1, col2) in each of the tables, I would expect the first version to be faster.

SQL Server : if column is not null show as a new row

I have a table like this:
id name col1 col2 col3 col4 col5 col6
----------------------------------------------
1 user b c e f g Null
I want to display the results like this as col4 and col5 is not null but do not show col6 as it is null:
id name col1 col2 col3 col4
----------------------------------
1 user b c e f
1 user b c e g(from col5)
You can use UNPIVOT for this. This automatically excludes NULL
SELECT id,
name,
col1,
col2,
col3,
ucol AS col4
FROM YourTable
UNPIVOT (x
FOR ucol IN (col4,
col5,
col6)) u
With UNION:
SELECT id, name, col1, col2, col3, col4 FROM tablename
UNION
SELECT id, name, col1, col2, col3, col5 FROM tablename
you can add to the 2nd select:
WHERE col5 IS NOT NULL
if this is what you want.
I would use cross apply:
select v.*
from t cross apply
(values (id, name, col1, col2, col3, col4),
(id, name, col1, col2, col3, col5)
) v(id, name, col1, col2, col3, col4);
If you want to unpivot and explicitly exclude null values:
select v.*
from t cross apply
(values (id, name, col1, col2, col3, col4),
(id, name, col1, col2, col3, col5),
(id, name, col1, col2, col3, col6)
) v(id, name, col1, col2, col3, col4)
where col4 is not null;

Replace Value in Column with Value in Different Column

I have a dataset that looks like this in SQL.
Col1 Col2 Col3
A 4 1
B 5 NULL
C 6 1
D 7 NULL
E 8 NULL
How do I add a new column with the values in Col2 with the values in Col3 if Col3 = 1, or else keep the existing values in Col2.
Final Expected Output:
Col1 Col2 Col3 Col4
A 4 1 1
B 5 NULL 5
C 6 1 1
D 7 NULL 7
E 8 NULL 8
I tried the coalesce function but I don't think that worked:
SELECT
Col1,
Col2,
Col3,
coalesce(Col3, Col2) AS Col4
FROM table1
Your description suggests a case expression :
select . . .
(case when col3 = 1 then col3 else col2 end) as col4
You could also express the above as
select . . .
(case when col3 = 1 then 1 else col2 end) as col4
For the data you provided, coalesce() should also work.
Try this:
SELECT
Col1,
Col2,
Col3,
CASE WHEN Col3 IS NOT NULL THEN Col3 ELSE Col2 END AS Col4
FROM table1
-- this should do what you want
SELECT
Col1,
Col2,
Col3,
CASE WHEN Col3 = 1 THEN Col3 ELSE Col2 END AS NewCOL
FROM table1
Insert into table2
select
Col1,
Col2,
Col3,
(case when col3 = 1 then 1 else col2 end) as col4
FROM table1

Group with summing in SQL Oracle

in a table below, I need to sum COL3 and COL5, grouped by COL2NAME.
So there will be 3 rows:
DC
Cred
Equi
... with summed values of COL3 and COL5.
How could I do it?
And here's the query from the screenshot:
select t.*
from (select COL1, COL2 as COL2NAME, sum(COL3A+COL3B) as COL3,
COL4 as COL4NAME, count(COL5NO) as COL5, DENSE_RANK()OVER(ORDER BY COL1) GROUPID
from TAB
group by COL1, COL2, COL4
) t
where GROUPID = 1
or GROUPID = 2
So just add a group by:
select col2name, sum(col3 + col5)
from (select COL1, COL2 as COL2NAME, sum(COL3A+COL3B) as COL3,
COL4 as COL4NAME, count(COL5NO) as COL5,
DENSE_RANK() OVER (ORDER BY COL1) as GROUPID
from TAB
group by COL1, COL2, COL4
) t
where GROUPID IN (1, 2)
group by col2name;