Finding Distinct values across multiple columns and rows in SQL - sql

I have data like this
Id code1 code2 code3 code4 code5 code6
1 2 3 4 5 6 7
1 4 5 2 3 7 6
1 7 6 5 2 3 4
1 5 7 6 4 3 2
1 7 5 6 3 2 4
I need to identify the distinct codes from this set of 6 codes across 5 rows and 6 columns and display them in any order of 6 rows with ID and code
OUTPUT
ID Code
1 7
1 6
1 2
1 3
1 5
1 4
enter image description here

One method is to use union :
select id, code
from (select id, code1 as code
from table t
union
select id, code2
from table t
. . .
select id, code6
from table t
) t;

Related

Get combination over two columns

Help me to get SQL
column 1
column 2
Id
DEP-1
1
1
DEP-1
1
2
DEP-1
2
3
DEP-2
3
4
DEP-3
1
5
DEP-3
2
6
DEP-3
3
7
DEP-3
2
8
DEP-3
3
9
I have above table I need to write SQL to display all DISTINCT combination of column 2 over column 1. for example DEP-1 has 1 and 2 in column 2. my final table has to look below.
column 1
column 2
Id
column 2 map
DEP-1
1
1
1~2
DEP-1
1
2
1~2
DEP-1
2
3
1~2
DEP-2
3
4
3
DEP-3
1
5
1~2~3
DEP-3
2
6
1~2~3
DEP-3
3
7
1~2~3
DEP-3
2
8
1~2~3
DEP-3
3
9
1~2~3
select origin.*, c2_map
from origin
join (
select c1, group_concat("~", c2) as c2_map
from (
select distinct c1, c2 from origin
) t1
group by c1
) t2
on origin.c1 = t2.c1
Note:
group_concat(sep, value) is an aggregate function, it depends on the database you use, it means join the values together using sep

Generate a serial number based on quantity column in sql

Hi Experts I have a table like this
T1
Order_no
Qty
1
3
2
5
3
1
4
3
I need to generate a column 'serial no' having values based on 'qty'
Output needed
OrderNo
Qty
SerailNo
1
3
1
1
3
2
1
3
3
2
5
1
2
5
2
2
5
3
2
5
4
2
5
5
3
1
1
4
3
1
4
3
2
4
3
3
Any suggestions?
Thanks in advance!!
You don't mention the specific database so I'll assume you are using PostgreSQL, aren't you?
You can use a Recursive CTE to expand the rows. For example:
with recursive
n as (
select order_no, qty, 1 as serial_no from t1
union all
select order_no, qty, serial_no + 1
from n
where serial_no < qty
)
select * from n order by order_no, serial_no
Result:
order_no qty serial_no
--------- ---- ---------
1 3 1
1 3 2
1 3 3
2 5 1
2 5 2
2 5 3
2 5 4
2 5 5
3 1 1
4 3 1
4 3 2
4 3 3
See running example at DB Fiddle.
EDIT FOR ORACLE
If you are using Oracle the query changes a bit to:
with
n (order_no, qty, serial_no) as (
select order_no, qty, 1 from t1
union all
select order_no, qty, serial_no + 1
from n
where serial_no < qty
)
select * from n order by order_no, serial_no
Result:
ORDER_NO QTY SERIAL_NO
--------- ---- ---------
1 3 1
1 3 2
1 3 3
2 5 1
2 5 2
2 5 3
2 5 4
2 5 5
3 1 1
4 3 1
4 3 2
4 3 3
See running example at db<>fiddle.
You should first provide the database you're using. Whether it's oracle, Sql Server, PostGreSQL will determine which procedural language to use. It's very likely that you'll need to do this in two steps:
1st: Duplicate the number of rows based on the column Qty using a decreasing loop
2nd: You'll need to create a sequential partionned column based on the Qty column

How to Subtotal Value with MAX

1.I have data as follows (just a subset - there are 20K records)
sku,id
1 1
1 2
1 2
1 2
1 3
1 4
1 1
1 2
1 3
1 4
1 4
1 4
1 5
1 6
1 6
2 1
2 1
2 2
2 3
2 3
2 3
2 4
2 4
2 5
2 5
2 6
2 7
2 1
2 2
2 3
The above values translate to
1 = 4 records
1 = 6 records
2 = 7 records
2 = 3 records
The MAX would just give me 6 for one and 7 for 2
The actual total is 1 = 10 and 2 = 10
How do I sum up to get the correct values?
You can use order by and some way of limiting rows. In standard SQL this would be:
select t.*
from t
order by id desc
fetch first 2 rows only;
However, some databases might use limit or select top or some other method.
No handling of ties here. Thousands of other questions handle this topic.
select sku, id
from (
select *, row_number() over (order by id desc) rn
from T
) t
where rn <= 2
order by rn desc;

Make a query to display unmatched data

I m having difficulty making a query that displays unmatched data in between 2 tables.
The tables are:
Employee data Salary data
ID Holidays ID Holiday
1 10 0 10
2 8 1 5
3 5 2 8
4 7 3 5
5 8 7 6
6 5 8 9
7 6 9 2
8 9 10 3
the primary key is ID for both tables.
I want my query result to contain all the values that does not match in both tables.
The type of output i want is something like this:
ID Holiday
0 10
1 10
1 5
4 7
5 8
6 5
9 2
10 3
I tried using unmatched query wizard but that only compares ID, not the Holiday column.
Please help me!
You could use a union of two exists queries:
SELECT ID, Holiday FROM Employee as e
WHERE NOT EXISTS (SELECT 1 FROM Salary as s WHERE s.ID = e.ID AND s.Holiday = e.Holiday)
UNION ALL
SELECT ID, Holiday FROM Salary as s
WHERE NOT EXISTS (SELECT 1 FROM Employee as e WHERE e.ID = s.ID AND e.Holiday = s.Holiday);

Adding non existing data to SQL query

My SQL query returns the following result (screenshot):
x y count
----------- ----------- -----------
1 1 10
1 2 2
2 4 3
2 5 5
4 1 5
5 1 8
what i want is x, y should always contain 1 to 5 values, even if the query doesn't return them, in the above scenario x is missing 3. How to add the missing values here that are between 1 & 5.
Thanks in Advance
First you need to generate the desired data. You can use a table of numbers for this. Use CROSS JOIN to generate all possible combinations of two tables. Finally, OUTER JOIN the generated data with your table.
In the following query I have used union to build a list of numbers instead of fetching them from a table. But the idea remains same:
SELECT XList.x, YList.y, #temp.count
FROM (
SELECT 1 AS x UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5
) AS XList
CROSS JOIN (
SELECT 1 AS y UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5
) AS YList
LEFT JOIN #temp ON XList.x = #temp.x AND YList.y = #temp.y
Result:
x y count
----------- ----------- -----------
1 1 10
2 1 NULL
3 1 NULL
4 1 5
5 1 8
1 2 2
2 2 NULL
3 2 NULL
4 2 NULL
5 2 NULL
1 3 NULL
2 3 NULL
3 3 NULL
4 3 NULL
5 3 NULL
1 4 NULL
2 4 3
3 4 NULL
4 4 NULL
5 4 NULL
1 5 NULL
2 5 5
3 5 NULL
4 5 NULL
5 5 NULL
You can do it this way:
select t1.x, t2.y, s.count from
(values(1),(2),(3),(4),(5)) t1(x) cross join
(values(1),(2),(3),(4),(5)) t2(y)
left join #temp s on t1.x = s.x and t2.y = s.y