Query For Hierarchy Order In SQL - sql

My Actual Table :
--------------------------------------------------
Col1 | Col2 | Col3 |
--------------------------------------------------
1 A 1
6 F 2
3 C 4
2 B 1
5 E 3
4 D 2
Expected Result :
------------------
|Columns Should Be|
------------------
A B F D C E
I need SQL query for this hierarchical logic.I have to get resultant logic using col 1 and col3 .Kindly help me out for this query.

I've just read your replies, I believe this is what you're after;
CREATE TABLE #TempData (Col1 int, Col2 varchar(1), Col3 int)
INSERT INTO #TempData (Col1, Col2, Col3)
VALUES
('1','A','1')
,('6','F','4')
,('6','C','2')
,('2','B','1')
,('5','E','3')
,('4','D','5')
SELECT
Col2
FROM #TempData
GROUP BY Col2
ORDER BY SUM(Col1)+SUM(Col3)
DROP TABLE #TempData

declare #table table (col1 int, col2 varchar(1), col3 int)
insert into #table (col1,col3)
values
(1, 1),
(6, 4),
(3, 2),
(2, 1),
(5, 3),
(4, 2)
/*
Col1 | Col2 | Col3 |
--------------------------------------------------
1 A 1
6 F 4
3 C 2
2 B 1
5 E 3
4 D 5
*/
select col1,
case
when col1 > col3 then char(col1 + 64)
else char(col3 + 64)
end as col2,
col3
from #table

in Sql server you may try this,
declare #t table (Col1 int, Col2 varchar(1), Col3 int)
INSERT INTO #t (Col1, Col2, Col3)
VALUES
('1','A','1')
,('6','F','2')
,('3','C','4')
,('2','B','1')
,('5','E','3')
,('4','D','2')
declare #str as varchar(100)=''
;with t as(select top 1 col1,col2,col3 from #t union all select t1.col1, t1.col2,t1.col3 from #t t1,t
where (t1.Col1!=t.Col1 and t1.Col3=t.Col1) )
select #str=#str+' '+col2 from t
select #str as col

Related

sql selecting unique rows based on a specific column

I have an table like this :
Col1 Col2 Col3 Col4
asasa 1 d 44
asasa 2 sd 34
asasa 3 f 3
dssd 4 d 2
sdsdsd 5 sd 11
dssd 1 dd 34
xxxsdsds2 d 3
erewer 3 sd 3
I am trying to filter out something like this based on Col1
Col1 Col2 Col3 Col4
asasa 1 d 44
dssd 4 d 2
sdsdsd 5 sd 11
xxxsdsds2 d 3
erewer 3 sd 3
I am trying to get the all unique rows based on the values in Col1. If I have duplicates in Col1, the first row should be taken.
I tried SELECT Col1 FROM tblname GROUP BY Col1 and got unique Col1 but extending it using * is giving me error.
You should be able to achieve your goal using something like the following:
WITH CTE AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Col1 ORDER BY Col2) AS rn FROM MyTable
)
SELECT * FROM CTE WHERE rn = 1
What it does is it creates a CTE (Common Table Expression) that adds a ROW_NUMBER on Col1, ordered by the data in row2.
In the outer select, we then only grab the rows from the CTE where the row number generated is 1.
Try this
;WITH CTE(
SELECT *,
ROW_NUMBER() OVER(PARTITIAN BY Col1 ORDER BY(SELECT NULL))RN
FROM tblname
)
SELECT Col1, Col2, Col3, Col4 FROM CTE;
Depending on the flavor of SQL that you have are using, what may help you are window functions.
In SQL Server, this can be accomplished with the FIRST_VALUE window function like so:
DROP TABLE IF EXISTS #vals;
CREATE TABLE #vals (COL1 VARCHAR(10), COL2 INT, COL3 VARCHAR(5), COL4 INT);
INSERT INTO #vals (COL1, COL2, COL3, COL4)
VALUES ('asasa', 1, 'd', 44),
('asasa', 2, 'sd', 34),
('asasa', 3, 'f', 3),
('dssd' , 4, 'd', 2),
('sdsdsd', 5, 'sd', 11),
('dssd', 1, 'dd', 34),
('xxxsdsds', 2, 'd', 3),
('erewer', 3, 'sd', 3);
SELECT *
FROM #vals
SELECT DISTINCT COL1,
FIRST_VALUE(COL2) OVER (PARTITION BY COL1 ORDER BY Col1) AS Col2,
FIRST_VALUE(COL3) OVER (PARTITION BY COL1 ORDER BY Col1) AS Col3,
FIRST_VALUE(COL4) OVER (PARTITION BY COL1 ORDER BY Col1) AS Col4
FROM #vals AS v1
This returns:
|COL1 | Col2 | Col3 | Col4|
|-----------|-----------|-----------|-------|
|asasa | 1 | d | 44 |
|dssd | 4 | d | 2 |
|erewer | 3 | sd | 3 |
|sdsdsd | 5 | sd | 11 |
|xxxsdsds | 2 | d | 3 |
which may then be ORDERed in whatever way is needed.
Select DISTINCT , should do the trick. Here is a good reference https://www.w3schools.com/sql/sql_distinct.asp

Addition with NULL values across multiple columns

Col1 Col2 Col3 SumCol
4 9 NULL 13
NULL 8 2 10
8 3 NULL 11
NULL 5 5 10
I have a table populated with columns Col1, Col2, and Col3, and I am trying to create a new column, SumCol. I know addition with NULL values is annoying so I appreciate any help
you can use below queries in sql-server
select id, col1, col2, col3, (coalesce(col1, 0) + coalesce(col2, 0) + coalesce(col3, 0)) total
from #tbl
OR
select id, col1, col2, col3, (ISNULL(col1, 0) + ISNULL(col2, 0) + ISNULL(col3, 0)) total
from #tbl
It is very simple by using XQuery or COALESCE().
SQL #1
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, Col1 INT, Col2 INT, Col3 INT);
INSERT INTO #tbl (Col1, Col2, Col3) VALUES
( 4 , 9, NULL),
(NULL, 8, 2 ),
( 8 , 3, NULL),
(NULL, 5, 5 );
-- DDL and sample data population, end
SELECT ID, Col1, Col2, Col3
, x.value('sum(/root/*/text())', 'INT') AS Summary
FROM #tbl
CROSS APPLY (SELECT Col1, Col2, Col3 FOR XML PATH(''), TYPE, ROOT('root')) AS t(x);
SQL #2
Based on the #DaleK's advice, a most common solution is below.
SELECT *
, Summary = COALESCE(Col1,0) + COALESCE(Col2,0) + COALESCE(Col3,0)
FROM #tbl;
SQL #3
A generic way tailored towards Col1, Col2, ..., ColN scenario.
SELECT ID, Col1, Col2, Col3
, x.value('sum(/root/*[not(local-name()="ID")]/text())', 'INT') AS Summary
FROM #tbl AS p
CROSS APPLY (SELECT * FROM #tbl AS c
WHERE c.ID = p.ID
FOR XML PATH(''), TYPE, ROOT('root')) AS t(x);
Output
+----+------+------+------+---------+
| ID | Col1 | Col2 | Col3 | Summary |
+----+------+------+------+---------+
| 1 | 4 | 9 | NULL | 13 |
| 2 | NULL | 8 | 2 | 10 |
| 3 | 8 | 3 | NULL | 11 |
| 4 | NULL | 5 | 5 | 10 |
+----+------+------+------+---------+
A computed column is often easier, if you want that calculation to always be available to anyone who queries the table:
ALTER TABLE YourTable
ADD COLUMN SumCol AS ISNULL(Col1, 0) + ISNULL(Col2, 0) + ISNULL(Col3, 0);

SQL Server - Select if one of all columns are unique

I want to select if one row where multiple columns are the same. For example:
col1 col2 col3 col4
a b 1 2
b b 1 2
a c 1 2
b b 1 3
a c 2 1
Condition: Select only if values of columns (col1, col2, col3) are different from other rows and value of col4 is max of rows which are the same.
For example expected Output is:
a b 1 2
b b 1 3
a c 1 2
a c 2 1
Yes possible, just use group by with max aggregation as
with tab(col1,col2,col3,col4) as
(
select 'a','b',1,2 union all
select 'b','b',1,2 union all
select 'a','c',1,2 union all
select 'b','b',1,3 union all
select 'a','c',2,1
)
select col1, col2, col3, max(col4) as col4
from tab
group by col1, col2, col3;
col1 col2 col3 col4
a b 1 2
a c 1 2
a c 2 1
b b 1 3
Rextester Demo
Mandatory NOT EXISTS solution... your condition written as a not exist query:
DECLARE #t TABLE (col1 varchar(100), col2 varchar(100), col3 int, col4 int);
INSERT INTO #t VALUES
('a', 'b', 1, 2),
('a', 'c', 1, 2),
('a', 'c', 2, 1),
('b', 'b', 1, 2),
('b', 'b', 1, 3);
SELECT *
FROM #t AS t
WHERE NOT EXISTS (
SELECT 1
FROM #t AS dup
WHERE dup.col1 = t.col1
AND dup.col2 = t.col2
AND dup.col3 = t.col3
AND dup.col4 > t.col4 -- outer row has smaller col4
)
Demo on DB Fiddle

updating a column in a table having duplicate rows

having problem updating a column in a table having duplicate rows..
I have a table "tab1" and its data looks like this..
Id col2 col3 col4 col5 col6 col7
1 xim M gtt tif 1 2
2 white M abc png 0 25
2 white M abc jpeg 0 25
3 gtc V ftt gif 4 72
This table contains duplicate Id's but differ only in col5.
this table contains around 4000 rows
i'd like to update col5 such that the output looks like this..
Id col2 col3 col4 col5 col6 col7
1 xim M gtt tif 1 2
2 white M abc png,jpeg 0 25
3 gtc V ftt gif 4 72
Is there a way to update this table using update statement, do i have to create a temp table for this update..??
I agree with the comments posted with by njk and Tony. It's not a good idea to denormalize your database, but perhaps your end goal is not so obvious and combining the image extensions is appropriate for your particular need.
This does what you are asking. I'm sure there's a way to do it with XML too without using a cursor in a function...
use tempdb
go
create table tmp (
id int,
col2 varchar(10),
col3 varchar(10),
col4 varchar(10),
col5 varchar(255),
col6 int,
col7 int
)
go
insert into tmp values
(1, 'xim', 'M', 'gtt', 'tif', 1, 2),
(2, 'white', 'M', 'abc', 'png', 0, 25),
(2, 'white', 'M', 'abc', 'jpeg', 0, 25),
(2, 'white', 'M', 'abc', 'gif', 0, 25),
(3, 'gtc', 'V', 'ftt', 'jpeg', 4, 72),
(3, 'gtc', 'V', 'ftt', 'tif', 4, 72),
(3, 'gtc', 'V', 'ftt', 'png', 4, 72),
(3, 'gtc', 'V', 'ftt', 'gif', 4, 72)
go
create function fnConcatCol5 (#id int) returns varchar(255) as
begin
declare #rtn varchar(255) = '', #val varchar(10)
declare cr cursor local for
select col5 from tmp where id = #id
open cr
fetch next from cr into #val
while ##fetch_status = 0
begin
set #rtn = #rtn + #val + ','
fetch next from cr into #val
end
close cr
deallocate cr
set #rtn = left(#rtn, datalength(#rtn) - 1)
return #rtn
end
go
-- it is more efficient to split up the 'distinct' and function call
-- into separate SQL statements so the function is only run *one* time
-- for each unique id
select distinct id, col2, col3, col4, col6, col7
into #temp
from tmp
select id, col2, col3, col4, dbo.fnConcatCol5(id) as col5, col6, col7
from #temp
go
drop table tmp, #temp
go
drop function fnConcatCol5
go
The data returned looks like this:
id col2 col3 col4 col5 col6 col7
----- ------- ------- ------- ------------------- ------- ----
1 xim M gtt tif 1 2
2 white M abc png,jpeg,gif 0 25
3 gtc V ftt jpeg,tif,png,gif 4 72

T-SQL Distinct column problem when trying to filter duplicates out

I have the following data
COL-1 COL-2
1 0TY/OK
1 0TY/OK
1 0TY/OK
1 0TY/OK
1 0TY/OK
2 2KP/L
2 2KP/L
2 2KP/L
2 2KP/L
2 2KP/L
3 7U5/2M
3 7U5/2M
3 7U5/2M
3 7U5/2M
And i want to construct a select query to retrieve that data in the output below
COL-1 COL-2 COL-3
1 0TY/OK 0TY/OK
1 0TY/OK 2KP/L
1 0TY/OK 7U5/2M
1 0TY/OK
1 0TY/OK
2 2KP/L
2 2KP/L
2 2KP/L
2 2KP/L
2 2KP/L
3 7U5/2M
3 7U5/2M
3 7U5/2M
3 7U5/2M
I want COL3 to return the distinct values of COL2
Using SELECT COL1, COL2, DISTINCT COL2 AS COL3 FROM MYTable does not work is SQL SERVER
Although I'm sure that some SQL wizard will be able to construct a way to do this, I feel the need to point out that conceptually this doesn't make sense - the values in the rows of column 3 are completely unrelated to the row values in columns 1 and 2.
Can you not simply return the distinct values of COL2 in a separate query?
SELECT DISTINCT COL2 FROM MyTable
(Note that you can return multiple resultsets from a single SQL query)
This is really unusual, and I can't see why you want this in one result set as it does not make any sense... There is no reason to associate the rows of the distinct query with the rows in the non-distinct query., but what you have to do is simply run both queries
Select Col1, Col2 From Table
Order By Col1, Col2
And
Select Distinct Col2 From Table
and join them together (To join them on row number, add a Row_Number() function to each query:
Select Col1, Col2, Col3
From (Select Row_Number() Over(Order By Col1, Col2)RowNum,
Col1, Col2
From Table) T1
Left Join
(Select Distinct Col2 As Col3,
(Select Count(Distinct Col2)
From Table
Where Col2 <= T2.Col3) RowNum
From Table) T2
On T2.RowNum = T1.RowNum
Try this out..
WITH MyTable AS
(
SELECT 1 Col1,CONVERT (VarChar (25), '0TY/OK') Col2 UNION ALL
SELECT 1,'0TY/OK' UNION ALL
SELECT 1,'0TY/OK' UNION ALL
SELECT 1,'0TY/OK' UNION ALL
SELECT 1,'0TY/OK' UNION ALL
SELECT 2,'2KP/L' UNION ALL
SELECT 2,'2KP/L' UNION ALL
SELECT 2,'2KP/L' UNION ALL
SELECT 2,'2KP/L' UNION ALL
SELECT 2,'2KP/L' UNION ALL
SELECT 3,'7U5/2M' UNION ALL
SELECT 3,'7U5/2M' UNION ALL
SELECT 3,'7U5/2M' UNION ALL
SELECT 3,'7U5/2M'
)
,
AllData AS
(
SELECT
*,
ROW_NUMBER () OVER (ORDER BY Col2) as Id
FROM MyTable
)
,
DistinctData AS
(
SELECT
Distinct Col2 AS Col3
FROM MyTable
),
DistinctWithRowNumber AS
(
SELECT
*,
ROW_NUMBER () OVER (ORDER BY Col3) as Id
FROM DistinctData
)
SELECT
Col1,
Col2,
Col3
FROM AllData
LEFT JOIN DistinctWithRowNumber
ON AllData.Id = DistinctWithRowNumber.Id
returns this result
Col1 Col2 Col3
----------- ------------------------- -------------------------
1 0TY/OK 0TY/OK
1 0TY/OK 2KP/L
1 0TY/OK 7U5/2M
1 0TY/OK NULL
1 0TY/OK NULL
2 2KP/L NULL
2 2KP/L NULL
2 2KP/L NULL
2 2KP/L NULL
2 2KP/L NULL
3 7U5/2M NULL
3 7U5/2M NULL
3 7U5/2M NULL
3 7U5/2M NULL
You can use CTEs to create a ROW_NUMBER and JOIN over those virtual columns.
DECLARE #t TABLE (
Col1 INT
,Col2 VARCHAR(10)
);
INSERT INTO #t VALUES (1, '0TY/OK');
INSERT INTO #t VALUES (1, '0TY/OK');
INSERT INTO #t VALUES (1, '0TY/OK');
INSERT INTO #t VALUES (1, '0TY/OK');
INSERT INTO #t VALUES (1, '0TY/OK');
INSERT INTO #t VALUES (2, '2KP/L,');
INSERT INTO #t VALUES (2, '2KP/L');
INSERT INTO #t VALUES (2, '2KP/L');
INSERT INTO #t VALUES (2, '2KP/L');
INSERT INTO #t VALUES (2, '2KP/L');
INSERT INTO #t VALUES (3, '7U5/2M');
INSERT INTO #t VALUES (3, '7U5/2M');
INSERT INTO #t VALUES (3, '7U5/2M');
INSERT INTO #t VALUES (3, '7U5/2M');
; WITH all_data AS (
SELECT
Col1
,Col2
,ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RowNum
FROM #t
),
distinct_data AS (
SELECT
Col2
,ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RowNum
FROM #t
GROUP BY
Col2
)
SELECT
all_data.Col1
,all_data.Col2
,distinct_data.Col2
FROM all_data
LEFT JOIN distinct_data ON all_data.RowNum = distinct_data.RowNum