SQL create new column based on number of instances in different column - sql

I want to create a new columns based on values in another column.
I have SQL database with below table:
col1 col2
2 H
2 H1
3 J
3 J1
3 J2
I try to transpose into the following:
col1 col2 col_new1 col_new2
2 H H1
3 J J1 J2
I use SQL report so can not define any variables or functions. Is there any CASE combination I could use?

This is slightly trickier than a simple pivot. Assuming you have at most three columns to pivot, you can do:
select col1,
max(case when seqnum = 1 then col2 end) as col2,
max(case when seqnum = 2 then col2 end) as col2_new1
max(case when seqnum = 3 then col2 end) as col2_new2
from (select t.*, row_number() over (partition by col1 order by col2) as seqnum
from t
) t
group by col1;
If you don't know the number of columns you want in the result set, then you cannot use a simple select. You need to use dynamic SQL.

Related

SQL DISTINCT based on a single column, but keep all columns as output

--mytable
col1 col2 col3
1 A red
2 A green
3 B purple
4 C blue
Let's call the table above mytable. I want to select only distinct values from col2:
SELECT DISTINCT
col2
FROM
mytable
When I do this the output looks like this, which is expected:
col2
A
B
C
but how do I perform the same type of query, yet keep all columns? The output would look like below. In essence I'm going through mytable looking at col2, and when there's multiple occurrences of col2 I'm only keeping the first row.
col1 col2 col3
1 A red
3 B purple
4 C blue
Do SQL functions (eg DISTINCT) have arguments I could set? I could imagine it to be something like KeepAllColumns = TRUE for this DISTINCT function? Or do I need to perform JOINs to get what I want?
You can use window functions, particularly row_number():
select t.*
from (select t.*, row_number() over (partition by col2 order by col2) as seqnum
from mytable t
) t
where seqnum = 1;
row_number() enumerates the rows, starting with "1". You can control whether you get the oldest, earliest, biggest, smallest . . .
You can use the QUALIFY clause in Teradata:
SELECT col1, col2, col3
FROM mytable
QUALIFY ROW_NUMBER() OVER(PARTITION BY col2 ORDER BY col2) = 1 -- Get 1st row per group
If you want to change the ordering for how to determine which col2 row to get, just change the expression in the ORDER BY.
With NOT EXISTS:
select m.* from mytable m
where not exists (
select 1 from mytable
where col2 = m.col2 and col1 < m.col1
)
This code will return the rows for which there is not another row with the same col2 and a smaller value in col1.

SQL DISTINCT for 2 Columns WHERE 3rd column = value

I'm trying to Select the Count of Distinct Columns Col 1 & Col 2 Where Col 3 = "Complete".
Firstly I don't know how to make Distinct apply to Col 1 & Col 2 together as opposed to Distinct about their own columns.
Secondly how to exclude Col 3 from the Distinct..
SELECT COUNT(*) AS Count From
(Select Distinct DP, RN From ECount
Where ET = 'Complete') as rows
Any thoughts?
example
col1 col2 col3
DP01 RN01 Complete yes
DP01 RN02 Incomplete
DP02 RN03 Complete
DP02 RN03 Incomplete
DP01 RN04 Complete yes
DP02 RN05 Complete yes
DP03 RN06 Incomplete
Result = 3
I don't think you need to include Column 3 (aka, col ET) in the SELECT part, you can just use it in the WHERE statement directly.
So in your example:
SELECT COUNT(*) AS Count FROM
(SELECT DISTINCT DP, RN FROM ECount
WHERE ET = 'Complete'
) AS rows
just don't select ET in subquery
SELECT COUNT(*) AS Count
From (
Select Distinct DP, RN
From ECount
Where ET = 'Complete'
) as rows
SELECT
Count(*) AS Count
FROM
(
SELECT
*
FROM
(
SELECT
*
FROM
`ECount`
ORDER BY
col3 DESC
) AS StrongIncomplete
GROUP BY
col1,
col2
) AS CompleteCut
WHERE
CompleteCut.col3 = 'Complete'
There are 3 SELECT statements.
The first one rearranges the table that 'Incomplete' is prior than 'Complete' in Col3.
The second one removes rows duplicated in Col1, Col2.
The third one removes rows where Col3 = 'Incomplete'

How to Get row values as columns in SQL?

I have a table Test with two columns.
Id Value
1 A
1 B
1 C
I want to get the result like below,
Id Value1 Value2 value3
1 A B C
How can I done this in SQL Server.
This is a pivot, but you don't have a column for the pivoting. row_number() can provide that. I usually use conditional aggregations for this.
select id,
max(case when seqnum = 1 then value end) as value1,
max(case when seqnum = 2 then value end) as value2,
max(case when seqnum = 3 then value end) as value3
from (select t.*,
row_number() over (partition by id order by (select null)) as seqnum
from t
) t
group by id;
Note that SQL tables represent unordered sets. So, there is no information about ordering and the values could be in any order. If a column does specify the ordering, then include that in the order by rather than select null.

DISTINCT for only one Column and other column random?

I have one Table name Demodata which have two column col1 and col2. data of table is
col1 col2
1 5
1 6
2 7
3 8
3 9
4 10
and after SELECT command we need this data
col1 Col2
1 5
6
2 7
3 8
9
4 10
is this possible then what is query please guide me
Try this
SELECT CASE WHEN RN > 1 THEN NULL ELSE Col1 END,Col2
FROM
(
SELECT *,Row_Number() Over(Partition by col1 order by col1) AS RN
From yourTable
) AS T
No it is not possible.
SQL Server result sets are row based not tree based. You must have a value for each column (alternatively a NULL value).
What you can do is grouping by col1 and run an aggregate function on the values of col2 (possibly the STUFF function).
You can do this in SQL, using row_number():
select (case when row_number() over (partition by col1 order by col2) = 1
then col1
end), col2
from table t
order by col1, col2;
Notice that the ordering is important. The way you have written the result set, the data is ordered by col1 and then col2. Result sets do not have an inherent ordering, unless you include an order by clause.
Also, I have used NULL for the missing values.
And, finally, although this can be done in SQL, it is often preferable to do these types of manipulations on the client side.
What do you want to select on the duplicates, an empty string, NULL, 0, ... ?
I presume NULL, you can use a CTE with ROW_NUMBER and CASE on col1:
WITH CTE AS(
SELECT RN = ROW_NUMBER() OVER (PARTITION BY col1
ORDER BY (SELECT 1))
, col1, col2
FROM Demodata
)
SELECT col1 = CASE WHEN RN = 1 THEN col1 ELSE NULL END, col2
FROM CTE
Demo

Add key to unique values in the SQl database

My SQL data looks like this:
Col1
A
A
A
B
B
C
D
I want to add a key to only unique values. So the end result will look like this:
Col1 Col2
A 1
A 1
A 1
B 2
B 2
C 3
D 3
How can I do this?
You can do this with the dense_rank() window function:
select col1, dense_rank() over (order by col1) as col2
from t;
This solves the problem as a query. If you want to actually change the table, then the code is more like:
alter table t add col2 int;
with toupdate as (
select t.*, dense_rank() over (order by col1) as newcol2
from t
)
update toupdate
set col2 = newcol2;