SQL return incremented number - sql

Hi I want to create a SQL function to return either 1 if a name in a column is unique, otherwise if that name is not unique then return an increment of 1. Here is what it should look lile:
NAME | Number
A | 1
B | 1
C | 1
C | 2
C | 3
D | 1
E | 1
The problem I am having is getting the number to increment.

ANSI SQL:
select name,
row_Number() over (partition by name order by name) as number
from your_table

CREATE TABLE #TEST (NAME CHAR(1))
INSERT INTO #TEST
SELECT 'A'
UNION ALL
SELECT 'A'
UNION ALL
SELECT 'B'
UNION ALL
SELECT 'B'
UNION ALL
SELECT 'B'
UNION ALL
SELECT 'C'
UNION ALL
SELECT 'D'
SELECT NAME, ROW_NUMBER() OVER (PARTITION BY NAME ORDER BY NAME) AS Number
FROM #TEST

If it's SQL Server, have a look here, at the Section C: Using ROW_NUMBER() with PARTITION:
http://msdn.microsoft.com/en-us/library/ms186734.aspx
SELECT
name
, ROW_NUMBER() OVER (PARTITION BY name ORDER BY name) number
FROM tbl

Related

How can I count the total no of rows which is not containing some value in array field? It should include null values as well

| names |
| -----------------------------------|
| null |
| null |
| [{name:'test'},{name:'test1'}] |
| [{name:'test'},{name:'test1'}] |
| [{name:'test1'},{name:'test2'}] |
I want to count the no of rows which does not have the value 'test' in the name key.
Here it should give answer as 3 (Row no 1, 2 and 5th row) because all these row do not contain the value 'test'.
Use below approach
select count(*)
from your_table
where 0 = ifnull(array_length(regexp_extract_all(names, r"\b(name:'test')")), 0)
you can test it with below data (that resemble whatever you presented in your question)
with your_table as (
select null names union all
select null union all
select "[{name:'test'},{name:'test1'}]" union all
select "[{name:'test'},{name:'test1'}]" union all
select "[{name:'test1'},{name:'test2'}]"
)
with output
Below approach will work,
with your_table as (
select null names union all
select null union all
select [('name','test'),('name','test1')] union all
select [('name','test'),('name','test1')] union all
select [('name','test1'),('name','test2')]
)
SELECT COUNT(*) as count FROM your_table
WHERE NOT EXISTS (
SELECT 1
FROM UNNEST(your_table.names) AS names
WHERE names IN (('name','test'))
)

How to merge two columns of same data type from table-1 to single column in Table-2?

What is the SQL to accomplish the below?
Table-1
id |name |aka-name
1 |Victor |vicky
2 |Nicholas |nicki
3 |Jefferson |jeff
Expected output:
Table -2
id |name
1 |Victor
2 |Nicholas
3 |Jefferson
4 |Jeff
5 |Nicki
6 |Vicki
select row_number() over(order by name) as id, name
from (
select name as name
from mytable
union all
select aka_name as name
from mytable) A
Here is a demo
And if you need the aka_name column to result in a first upper case letter then you can use this:
select row_number() over(order by name) as id, name
from (
select name as name
from mytable
union all
select UPPER(LEFT(aka_name,1))+LOWER(SUBSTRING(aka_name,2,LEN(aka_name))) as name
from mytable) A

case statement after where clause to omit the row of data if satisfied

Hi I have a table as below and I'm trying to extract the data from them if and only if the below condition is satisfied.
ID Rank
45689 1
54789 2
98765 1
96541 2
98523 3
92147 4
96741 2
99999 10
If the ID starts with 4 and 9 or 5 and 9 and have same Rank then omit them. If ID starts with 9 and no matching Rank with other ID (starting with 4 or 5) then show them as result.
So My Output should look like
ID Rank
98523 3
92147 4
99999 10
How can I use case statement in where clause to filter the data?
If I understand correctly, you want to select only those ID that begin with a 9, and have a rank that is not also the rank of (another) ID that begins with 4 or 5. Is that correct?
The query below is for the case ID is of string data type (although it will work OK, probably, if ID is numeric data type - through implicit conversion).
select *
from your_table
where id like '9%'
and rank not in (
select rank
from your_table
where substr(id, 1, 1) in ('4', '5')
)
;
One option would be using COUNT() analytic function along with a conditional aggregation such as
WITH t2 AS
(
SELECT SUM(CASE WHEN SUBSTR(id,1,1) IN ('5','9') OR
SUBSTR(id,1,1) IN ('4','9') THEN 1 END ) OVER
(PARTITION BY Rank) AS count, t.*
FROM t -- your original table
)
SELECT id, rank
FROM t2
WHERE count = 1
Demo
You can use an analytic function to only query the table once:
SELECT id,
rank
FROM (
SELECT t.*,
COUNT( CASE WHEN id LIKE '4%' OR id LIKE '5%' THEN 1 END )
OVER ( PARTITION BY Rank )
AS num_match
FROM table_name t
WHERE id LIKE '4%'
OR id LIKE '5%'
OR id LIKE '9%'
)
WHERE id LIKE '9%'
AND num_match = 0;
Which, for the sample data:
CREATE TABLE table_name ( ID, Rank ) AS
SELECT 45689, 1 FROM DUAL UNION ALL
SELECT 54789, 2 FROM DUAL UNION ALL
SELECT 98765, 1 FROM DUAL UNION ALL
SELECT 96541, 2 FROM DUAL UNION ALL
SELECT 98523, 3 FROM DUAL UNION ALL
SELECT 92147, 4 FROM DUAL UNION ALL
SELECT 96741, 2 FROM DUAL UNION ALL
SELECT 99999, 10 FROM DUAL;
Outputs:
ID | RANK
----: | ---:
98523 | 3
92147 | 4
99999 | 10
db<>fiddle here

How to select distinct records from individual column in sql table

I want to retrieve distinct rows from each column in this sql table
My table
1 Apple
2 Banana
3 Apple
2 Apple
1 Orange
I want the result like this:
1 Apple
2 Banana
3 Orange
Please help me with this
You can get the distinct names by doing:
select distinct name
from table t;
You can add the first column by doing:
select row_number() over (order by name) as id, name
from (select distinct name
from table t
) t;
Most databases support the ANSI standard row number. You haven't tagged this with the database, so that is the most general solution.
EDIT:
Oh, you want two columns each with values. I would approach this as a full outer join:
select nu.num, na.name
from (select num, row_number() over (order by num) as seqnum
from table
group by num
) nu full outer join
(select name, row_number() over (order by name) as seqnum
from table t
group by name
) na
on nu.seqnum = na.seqnum;
Each subquery enumerates the values in each column. The full outer join makes sure that you have values even when they are missing on one side or the other.
Please try it
select *,row=rank() over(order by name) from (SELECT distinct name FROM abc) as cte
or
with cte as
(
SELECT distinct name FROM abc
)
select *,row=rank() over(order by name) from cte
Output
| row | Name |
|-----------|----------|
| 1 | Apple |
| 2 | Banana |
| 3 | Orange |
Proof of concept.
Tested on Oracle 11.2
WITH
MyTable (firstName, lastName) AS (
SELECT '1', 'Apple' FROM DUAL UNION ALL
SELECT '2', 'Banana' FROM DUAL UNION ALL
SELECT '3', 'Apple' FROM DUAL UNION ALL
SELECT '2', 'Apple' FROM DUAL UNION ALL
SELECT '4', 'Apple' FROM DUAL UNION ALL
SELECT '1', 'Orange' FROM DUAL),
Ranked AS (
SELECT DISTINCT
firstName
, DENSE_RANK() OVER (ORDER BY firstName) AS fnRnk
, lastName
, DENSE_RANK() OVER (ORDER BY lastName) AS lnRnk
FROM MyTable
)
SELECT
DISTINCT R1.firstName, R2.lastName FROM Ranked R1 FULL OUTER JOIN Ranked R2 ON R1.fnRnk = R2.lnRnk ORDER BY lastName NULLS LAST, firstName
;
Returns
| FIRSTNAME | LASTNAME |
|-----------|----------|
| 1 | Apple |
| 2 | Banana |
| 3 | Orange |
| 4 | (null) |
Added a row to the original data to demonstrate columns of different length.
SQL Fiddle

Oracle select pivot query to put row adjacent to their counter part using generic column name

I have a table which each entry has a counter pair
Customer
Name Value
Bob 3
Bob 4
Sam 0
Sam 1
Joe 9
I want the following result
Customer
Name Value1 Value2
Bob 3 4
Sam 0 1
Joe 9
I have read this thread, Oracle query to put rows at odd number adjacent to even number, but I want to avoid using the MOD function instead possible using pivot instead.
You can't use the pivot statement here, if you have only two value for each name (it also works with dates, because we can use max and min for dates):
select name, min(value) value1, nullif(max(value), min(value)) value2
from customer_tables
group by name
If Bob, Sam and other have more that two value:
with t (Name, Value) as (
select 'Bob',3 from dual union all
select 'Bob',4 from dual union all
select 'Sam',0 from dual union all
select 'Sam',1 from dual union all
select 'Joe',9 from dual
), t1 (name, value, rn) as (
select name, value, ROW_NUMBER() OVER(partition by name order by value) from t
)
select * from t1
pivot XML (
max(value)
for rn in (ANY)
)
SQL> l
1 with t (Name, Value) as (
2 select 'Bob',3 from dual union all
3 select 'Bob',4 from dual union all
4 select 'Sam',0 from dual union all
5 select 'Sam',1 from dual union all
6 select 'Joe',9 from dual
7 ), t1 (name, value, rn) as (
8 select name, value, ROW_NUMBER() OVER(partition by name order by value) from t
9 )
10 select * from t1
11 pivot XML (
12 max(value)
13 for rn in (ANY)
14* )
SQL> /
NAM RN_XML
--- --------------------------------------------------------------------------------
Bob <PivotSet><item><column name = "RN">1</column><column name = "MAX(VALUE)">3</col
umn></item><item><column name = "RN">2</column><column name = "MAX(VALUE)">4</co
lumn></item></PivotSet>
Joe <PivotSet><item><column name = "RN">1</column><column name = "MAX(VALUE)">9</col
umn></item></PivotSet>
Sam <PivotSet><item><column name = "RN">1</column><column name = "MAX(VALUE)">0</col
umn></item><item><column name = "RN">2</column><column name = "MAX(VALUE)">1</co
lumn></item></PivotSet>
Read more about pivot here