I want a SQL query to display the following data
Input Data:
ID GroupID Data
1 1 Hello
2 1 Null
3 1 Null
4 1 World
5 2 Niladri
6 2 XXX
7 2 Null
8 2 PPP
9 2 Null
10 2 Null
11 2 Null
12 2 LLL
as
Output Data:
GroupID MergedData
1 Hello2World
2 NiladriXXX1PPP3LLL
I need to group the data on GroupID and display the result as Hello2World
-->Hello is related to GroupID 1
-->2 is count of NULLS
-->World is related to GroupID 1
Similarly for GroupID 2.
Kindly suggest?
Thanks
As you did not mention your DBMS, this is a solution for PostgreSQL:
SELECT groupid,
string_agg(temp_data,'')
FROM (
SELECT id,
groupid,
data,
CASE
WHEN data IS NULL
THEN cast(max(rn) over (partition by groupid, data) as varchar)
ELSE data
END AS temp_data,
row_number() over (partition by groupid, data) as group_rn
FROM (
SELECT id,
groupid,
data,
CASE
WHEN data IS NULL
THEN row_number() over (partition by groupid,data)
ELSE NULL
END AS rn
FROM foo
) t1
ORDER BY id
) t2
WHERE group_rn in (0,1)
GROUP BY groupid
If your DBMS supports ANSI windowing functions and has something similar like the string_agg() function then this should be portable to your DBMS as well.
Related
How to select the value from the table based on category_id?
I have a table like this. Please help me.
Table A
ID Name category_id
-------------------
1 A 1
2 A 1
3 B 1
4 C 2
5 C 2
6 D 2
7 E 3
8 E 3
9 F 3
How to get the below mentioned output from table A?
ID Name category_id
--------------------
1 A 1
2 A 1
4 C 2
5 C 2
7 E 3
8 E 3
Give a row number for each row based on group by category_id and sort by ascending order of ID. Then select the rows having row number 1 and 2.
Query
;with cte as (
select [rn] = row_number() over(
partition by [category_id]
order by [ID]
), *
from [your_table_name]
)
select [ID], [Name], [category_id]
from cte
where [rn] < 3;
Kindly run this query It really help You Out.
SELECT tbl.id,tbl.name, tbl.category_id FROM TableA as tbl WHERE
tbl.name IN(SELECT tbl2.name FROM TableA tbl2 GROUP BY tbl2.name HAVING Count(tbl2.name)> 1)
Code select all category_id from TableA which has Name entries more then one. If there is single entry of any name group by category_id then such data will be excluded. In above example questioner want to eliminate those records that have single Name entity like wise category_id 1 has name entries A and B among which A has two entries and B has single entry so he want to eliminate B from result set.
id name
--------------
1 ACTIVE
2 NULL
3 NULL
4 NULL
5 COMPLETED
6 NULL
7 COMPLETED
8 COMPLETED
9 ACTIVE
10 NULL
11 ACTIVE
Output:
id name
--------------
1 ACTIVE
2 ACTIVE
3 ACTIVE
4 ACTIVE
5 COMPLETED
6 COMPLETED
7 COMPLETED
8 COMPLETED
9 ACTIVE
10 ACTIVE
11 ACTIVE
Task: retrieve null records with above values without using a loop and update.
in will come select statement.
With DDL and Sample data:
CREATE TABLE #Sample (ID int, [Name] varchar(9));
INSERT INTO #Sample
VALUES (1,'ACTIVE'),
(2,NULL),
(3,NULL),
(4,NULL),
(5,'COMPLETED'),
(6,NULL),
(7,'COMPLETED'),
(8,'COMPLETED'),
(9,'ACTIVE'),
(10,NULL),
(11,'ACTIVE');
GO
SELECT *
FROM #Sample;
UPDATE S
SET [Name] = (SELECT TOP 1 [Name]
FROM #Sample sq
WHERE sq.ID < S.ID
AND sq.[Name] IS NOT NULL
ORDER BY sq.ID DESC)
FROM #Sample S
WHERE S.[Name] IS NULL;
SELECT *
FROM #Sample;
GO
DROP TABLE #Sample;
Assuming window functions are supported in your version of SQL Server, this can be done with classifying consecutive nulls in the name column to the same group as the first occurring name for an id. Then use max to get the name for the group and use it to update.
with cte as (
select id,name,max(name) over(partition by grp) as new_name
from (select *, sum(case when name is null then 0 else 1 end) over(order by id) as grp
from tbl
) t
)
update cte set name = new_name
where name is null;
I am unable to find the logic for below question in SQL Server.
I have a table like below.
id ParentID
---------------
1 NULL
2 NULL
3 1
4 2
5 3
6 5
I need a query which will return hierarchy of a row, like this:
Hierarchy id ParentID
----------------------------
1 1 NULL
1 2 NULL
2 3 1
2 4 2
3 5 3
4 6 5
I will explain the hierarchy:
For any row if ParentId is null then Hierarchy will be 1
Any row if ParentId is not null and ParentId's ParentId is null then 2
Any row if ParentId is not null, ParentId's ParentId is not null and next ParentId's ParentId is null then 3
And it goes on
How can write the query for this logic.
You can achieve this with a recursive query:
(in the below example your initial table data is stored in #a):
;With DATA AS (
SELECT 1 as hierarchy
,Id
,parentid
from #a
where parentid is null
UNION ALL
SELECT Data.Hierarchy + 1
,a.id
,a.parentid
FROM #a a
INNER JOIN DATA
ON Data.id = a.parentid
)
SELECT *
FROM DATA
ORDER BY hierarchy, Id
I am working in Excel 2013 and connecting to SQL Server with an ODBC connection
I have a table like this:
id PhoneNumber Caller
--------------------------------
1 915869850 John
2 912586985 Mary
3 963285874 John
4 915869850 Richard
5 965878965 James
6 925869753 Richard
8 963285874 James
and I need to be add a column that identifies the first time a phone number is called and ignores it on the subsequent times...
Like this:
id PhoneNumber Caller First Time
-----------------------------------------
1 915869850 John 1
2 912586985 Mary 1
3 963285874 John 1
4 915869850 Richard 0
5 965878965 James 1
6 925869753 Richard 1
8 963285874 James 0
Is it possible to do so?
Can you help me?
Use ROW_NUMBER() window function like below:
SELECT *, CASE WHEN (ROW_NUMBER() OVER
(PARTITION BY PhoneNumber ORDER BY id))=1 THEN 1 ELSE 0 END FirstTime
FROM Src
ORDER BY id
Assuming SQL Server 2005+ you can use ROW_NUMBER and then a CASE expression:
WITH CTE AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY PhoneNumber ORDER BY id)
FROM dbo.Phones
)
SELECT id,
PhoneNumber,
[Caller],
CASE WHEN RN = 1 THEN 1 ELSE 0 END [First Time]
FROM CTE;
Another solution:
WITH FirstCallList AS
(
SELECT
MIN([id]) AS FirstIdForNumber
FROM
Calls
GROUP BY
PhoneNumber
)
SELECT
Calls.id
,Calls.PhoneNumber
,Calls.Caller
,CASE WHEN FirstCallList.FirstIdForNumber IS NULL THEN 0 ELSE 1 END AS FirstTime
FROM
Calls
LEFT OUTER JOIN FirstCallList ON Calls.id = FirstCallList.FirstIdForNumber
ORDER BY
Calls.id
;
The classic approach to this was a self join or a scalar subquery like this:
select id, PhoneNumber,
case
when id = (
select min(p2.id) from <Phones> p2
where p2.PhoneNumber = p.PhoneNumber
) then 1 else 0
end as [First Time]
from <Phones> p
This question already has answers here:
Efficiently convert rows to columns in sql server
(5 answers)
Closed 7 years ago.
I am trying to join two tables and then parse out the results into separate columns like so:
Table1:
Customer_ID
----------
1
2
3
Table2:
Customer_ID ListID
------------------
1 1
1 2
1 5
2 1
2 3
Desired Results:
Customer_ID ListID1 ListID2 ListID3
-----------------------------------
1 1 2 5
2 1 3
3
I used a LEFT JOIN to combine the tables and a GROUP BY to group columns with the same Custmer_ID as shown here:
SELECT MIN([Table1].[Customer_ID])
,MIN([Table2].[ListID])
FROM [Table1]
LEFT JOIN [Table2]
ON [Table2].[Customer_ID] = [Table1].[Customer_ID]
GROUP BY [Table1].[Customer_ID]
Current Results:
Customer_ID ListID
------------------
1 1
2 1
3 NULL
I can't figure out where to go from here to parse the ListID's into separate columns. Is there a way to iterate through the ListID's?
This is unique in that the column that you want to pivot for doesn't exist. You can create it with the Row_number window function. It looks like this:
SELECT Customer_ID, [1] ListID1, [2] ListID2, [3] ListID3
FROM
(select Table1.Customer_ID,
Table2.ListID,
ROW_NUMBER() over (Partition by Table1.Customer_ID Order By Table2.ListID) RowNum
from Table1
LEFT JOIN Table2
ON Table2.[Customer_ID] = Table1.[Customer_ID]) as SourceTable
PIVOT
(
max(ListID)
FOR RowNum IN ([1], [2], [3])
) AS PivotTable
This will only show the top three ListID values in the columns. You can add more RowNum values if you need more.