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

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;

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

SELECT only partially distinct data

How can you do a SELECT statement with a partial distinct?
Col1 Col2 Col3 Col4
data1 data2 data3 abc
data2 data3 data2 abcde
data1 data2 data3 abcfef3f
For the dataset above, only return those with a distinct (Col1, Col2, Col3):
Col1 Col2 Col3 Col4
data1 data2 data3 abc
data2 data3 data2 abcde
Ultimately I want to insert this into a temp table like below.
INSERT INTO #tmp
(
[Col1],
[Col2],
[Col3],
[Col4]
)
SELECT DISTINCT Col1, Col2, Col3, Col4
FROM store s
INNER JOIN address a ON s.addressid = a.id
since you don't care which of col4 values you want, you could get the smallest one, and do
SELECT Col1, Col2, Col3, min(Col4)
FROM store s
INNER JOIN address a ON s.addressid = a.id
GROUP BY Col1, Col2, Col3
You also can use CTE with Ranking function to do that.
; with subQry as (
select col1, col2, col3, col4, rownumber() over(partition by col1, col2, col3 order by col1, col2, col3) rnk
FROM store s
INNER JOIN address a ON s.addressid = a.id
)
select * from subQry where rnk = 1;

duplicates with respect to only that column for every column in the table

col1 col2 col3 col4 col5
9607788997 9607788997 778897 778897 7788997
9607788997 9607788997 778897 778897 7788997
9607788998 9607788997 778894 778897 7788997
9607788999 9607788967 778894 778897 7788997
9607788999 9607788969 778894 778899 778899
this is my table. now I need to find only the duplicate among columns and display the duplicates with respect to only that column
and I should get the below table,
need SQL query. Thanks in advance
col1 col2 col3 col4 col5
9607788997 9607788997 778897 778897 7788997
9607788999 778894
You can do what you want using the ANSI-standard dense_rank() function and aggregation:
select max(col1) as col1,
max(col2) as col2,
max(col3) as col3,
max(col4) as col4,
max(col5) as col5
from ((select col1, null as col2, null as col3, null as col4, null as col5,
dense_rank() over (order by col1) as seqnum
from t
group by col1
) union all
(select null, col2, null as col3, null as col4, null as col5,
dense_rank() over (order by col2)
from t
group by col2
) union all
(select null, null as col2, col3, null as col4, null as col5,
dense_rank() over (order by col3)
from t
group by col3
) union all
(select null, null as col2, null as col3, col4, null as col5,
dense_rank() over (order by col4)
from t
group by col4
) union all
(select null, null as col2, null as col3, null as col4, col5,
dense_rank() over (order by col5)
from t
group by col5
)
) tt
group by seqnum

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;

Distinct records based on some columns in 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