How to divide a name into rows in sql server? - sql

I want a name to be passed as a parameter to a stored procedure and when i execute this stored procedure, it should divide the name into rows.
For example if pass 'Peter', output should be
P
e
t
e
r

The fastest method to do this would be with a Tally and SUBSTRING. I assume that the name won't be longer than 100 characters, and that (as it's a name) it's an nvarchar rather than a varchar. You can then do something like this:
DECLARE #Name nvarchar(100) = N'Peter';
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP(DATALENGTH(#Name) / 2) --If a varchar, remove the / 2
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2)
SELECT SUBSTRING(#Name,T.I,1) AS C
FROM Tally T;

declare #input varchar(max);
set #input = 'Peter'
declare #table TABLE (char varchar(1));
while (LEN(#input)> 0)
begin
insert into #table select substring(#input,1,1)
select #input = RIGHT(#input,Len(#input)-1)
end
select * from #table
GO
| char |
| :--- |
| P |
| e |
| t |
| e |
| r |
declare #T table
(
ID int identity,
names varchar(10)
)
insert into #T
select 'Peter'
;with cte as
(
select ID,
left(names, 1) as Data,
stuff(names, 1, 1, '') as remains
from #T
where len(names) > 0
union all
select ID,
left(remains, 1) as Data,
stuff(remains, 1, 1, '') as remains
from cte
where len(remains) > 0
)
select ID,
Data
from cte
order by ID
ID | Data
-: | :---
1 | P
1 | e
1 | t
1 | e
1 | r
db<>fiddle here

Related

How to populate given SQL records to all UserID

I have a table in this form:
id | firstname | lastname | userid
---+-----------+------------------------
1 | john | smith | 545868-5434-343435-35353
2 | adam | finger | 545868-5434-343435-35353
3 | teri | marti | 545868-5434-343435-35353
4 | pei | port | 545868-5434-343435-35353
In the DB i have many userid i need to populate the very same firstname and lastname to all userid found in the Database
Here is my SQl Query
SELECT
cID, c.firstname,c.lastname,
[s].UserID,c.OwnerID
FROM
Customer INNER JOIN [s] ON c.OwnerID = [s].UserID AND c.AssignedtoID =
[s].UserID AND c.CreatedByUserID = [s].UserID
AssignedtoID is the same as UserID
is this helpful for you.?
Create table #tmpCustomer (id int, firstname VARCHAR(50),lastname VARCHAR(50),userid VARCHAR(100))
INSERT INTO #tmpCustomer
SELECT 1, 'john','smith','545868-5434-343435-35353'
union
SELECT 2,'adam','finger','545868-5434-343435-35353'
union
SELECT 3,'teri','marti','545868-5434-343435-35353'
union
SELECT 4, 'pei','port','545868-5434-343435-35353'
union
SELECT 5, 'abc','xyz','545868-5434-343435-35354'
union
SELECT 6, 'mno','ert','545868-5434-343435-35354'
--select * from #tmpCustomer
;with cte1 AS(Select row_number()over(partition by userid order by id) rn,* from #tmpCustomer ),
cte2 AS (select * from cte1 where rn=1 )
update t
set t.firstname=c.firstname
from #tmpCustomer t
JOIN cte2 c on t.userid=c.userid
select * from #tmpCustomer
drop table #tmpCustomer
i don't know if i good understand your question, try solution posted below
DECLARE #cust as table (firstname varchar(20),lastname Varchar(20))
Insert #cust
values
('Suzan','Smith')
declare #id as table (id int identity,anything varchar(20),row_inserted datetime2 default (cast(sysdatetime() as datetime2)))
INSERT #id
(anything,row_inserted)
SELECT 'x' ,'20180305'
union all
select 'y','20180305'
union all
select 'z','20180305'
select s.id,c.firstname,
c.lastname
from #id as s
cross join #cust as c

MS SQL how to select n rows from table even if table has n - x rows

I have a table with a following data:
ID | Name
---------
1 | John
2 | Alice
And when I want to select 5 rows I want to get the next data:
ID | Name
---------
1 | John
2 | Alice
1 | John
2 | Alice
1 | John
Is there any ideas how to make this?
-- to create a sample table.
CREATE TABLE table1 (ID BIGINT, NAME VARCHAR(255))
INSERT INTO table1 VALUES (1, 'John'), (2, 'Alice')
-- set number of rows you need
DECLARE #RowsReqd INT = 5
-- find out the max ID we want to generate
DECLARE #Limit INT
SELECT #Limit = MAX(ID) FROM table1
-- generate the list
;WITH NumbersList
AS (
SELECT 1 AS Number, 1 AS ID
UNION ALL
SELECT Number + 1, Number % #Limit + 1 FROM NumbersList
WHERE Number < #RowsReqd
)
SELECT T.*
FROM NumbersList NL
INNER JOIN table1 T ON T.ID = NL.ID
ORDER BY NL.Number
OPTION (MAXRECURSION 10000) -- increase this value to generate more numbers
OUTPUT:
ID NAME
1 John
2 Alice
1 John
2 Alice
1 John
Works for n > 1 rows:
;WITH cte AS (
SELECT *
FROM (VALUES
(1, 'John'),
(2, 'Alice')
) AS t(ID, Name)
)
,res AS (
SELECT id,
name,
ROW_NUMBER() OVER (partition by id ORDER BY ID) as pid
FROM cte
UNION ALL
SELECT c.id,
c.name,
pid + 1
FROM res r
INNER JOIN cte c
ON pid = c.id
)
SELECT TOP 5
id,
name
FROM res
Output:
id name
----------- -----
1 John
2 Alice
1 John
2 Alice
1 John
(5 row(s) affected)

How to comapre two columns of a table in sql?

In a table there are two columns:
-----------
| A | B |
-----------
| 1 | 5 |
| 2 | 1 |
| 3 | 2 |
| 4 | 1 |
-----------
Want a table where if A=B then
-------------------
|Match | notMatch|
-------------------
| 1 | 5 |
| 2 | 3 |
| Null | 4 |
-------------------
How can i do this?
I tried something which shows the Matched part
select distinct C.A as A from Table c inner join Table d on c.A=d.B
Try this:
;WITH TempTable(A, B) AS(
SELECT 1, 5 UNION ALL
SELECT 2, 1 UNION ALL
SELECT 3, 2 UNION ALL
SELECT 4, 1
)
,CTE(Val) AS(
SELECT A FROM TempTable UNION ALL
SELECT B FROM TempTable
)
,Match AS(
SELECT
Rn = ROW_NUMBER() OVER(ORDER BY Val),
Val
FROM CTE c
GROUP BY Val
HAVING COUNT(Val) > 1
)
,NotMatch AS(
SELECT
Rn = ROW_NUMBER() OVER(ORDER BY Val),
Val
FROM CTE c
GROUP BY Val
HAVING COUNT(Val) = 1
)
SELECT
Match = m.Val,
NotMatch= n.Val
FROM Match m
FULL JOIN NotMatch n
ON n.Rn = m.Rn
Try with EXCEPT, MINUS and INTERSECT Statements.
like this:
SELECT A FROM TABLE1 INTERSECT SELECT B FROM TABLE1;
You might want this:
SELECT DISTINCT
C.A as A
FROM
Table c
LEFT OUTER JOIN
Table d
ON
c.A=d.B
WHERE
d.ID IS NULL
Please Note that I use d.ID as an example because I don't see your schema. An alternate is to explicitly state all d.columns IS NULL in WHERE clause.
Your requirement is kind of - let's call it - interesting. Here is a way to solve it using pivot. Personally I would have chosen a different table structure and another way to select data:
Test data:
DECLARE #t table(A TINYINT, B TINYINT)
INSERT #t values
(1,5),(2,1),
(3,2),(4,1)
Query:
;WITH B AS
(
( SELECT A FROM #t
EXCEPT
SELECT B FROM #t)
UNION ALL
( SELECT B FROM #t
EXCEPT
SELECT A FROM #t)
), A AS
(
SELECT A val
FROM #t
INTERSECT
SELECT B
FROM #t
), combine as
(
SELECT val, 'A' col, row_number() over (order by (select 1)) rn FROM A
UNION ALL
SELECT A, 'B' col, row_number() over (order by (select 1)) rn
FROM B
)
SELECT [A], [B]
FROM combine
PIVOT (MAX(val) FOR [col] IN ([A], [B])) AS pvt
Result:
A B
1 3
2 4
NULL 5

SQL: Merging rows with comma separated values in columns

We have a table like this:
Group | User | Team
-------------------
Grp1 | U1 | T1,T2
Grp1 | U2 | T1,T2,T3
Grp1 | U3 | T4
Grp2 | U4 | T2,T4
Grp2 | U5 | T5
I want to create a view which has the data like this:
Group | Teams
-------------
Grp1 | T1,T2,T3,T4
Grp2 | T2,T4,T5
Can somebody please help me? I tried doing few trail and errors and finally I am at a state where I am not even sure where to start from now
Here is my approach.
I am using cursor but you can do it in while loop also.
The only issue is that teams in new table are not distinct but I think you can play with string commands and it will sort the issue.
CREATE TABLE #tbl1 ([GROUP] varchar(20), [USER] VARCHAR(20), team VARCHAR(20))
INSERT INTO #tbl1 ( [GROUP], [USER],team )
VALUES ( 'Grp1', 'U1', 'T1,T2'), ( 'Grp1', 'U2', 'T3,T4'), ( 'Grp1', 'U3', 'T4'),
( 'Grp2', 'U1', 'T1,T2'), ( 'Grp2', 'U2', 'T3,T4')
CREATE TABLE #tbl2 ([GROUP] varchar(20), team VARCHAR(20))
DECLARE #ListOfteams VARCHAR(max)
DECLARE #grp VARCHAR(20)
DECLARE Curs CURSOR FAST_FORWARD
FOR
SELECT DISTINCT [GROUP]
FROM #tbl1 AS T
OPEN Curs
FETCH NEXT FROM Curs INTO #grp
WHILE ##FETCH_STATUS = 0
BEGIN
SET #ListOfteams= ''
SELECT #ListOfteams= #ListOfteams+ [Team] + ',' FROM #tbl1 AS CL WHERE CL.[GROUP] = #grp ORDER BY [CL].[USER]
INSERT INTO #tbl2 ( [GROUP],team )
SELECT DISTINCT #grp,
SUBSTRING(#ListOfteams, 1, LEN(#ListOfteams)-1)
FROM #tbl1 AS T
WHERE T.[GROUP] = #grp;
FETCH NEXT FROM Curs INTO #grp
END
CLOSE Curs
DEALLOCATE Curs;
SELECT *
FROM #tbl2 AS T
Here is ow it works: http://rextester.com/BYK57259
+-------+----------------+
| GROUP | team |
+-------+----------------+
| Grp1 | T1,T2,T3,T4,T4 |
| Grp2 | T1,T2,T3,T4 |
+-------+----------------+
Here is how am doing this, first convert the comma seperated team names to individual rows based on their groups and then take the unique team grp and team names. Now apply the listagg function for the unique team names to achieve the result.
with t as
(
select 'Grp1' grp,'U1' user1,'T1,T2' team from dual
union all
select 'Grp1','U2','T1,T2,T3' from dual
union all
select 'Grp1','U3','T4' from dual
union all
select 'Grp2','U4','T2,T4' from dual
union all
select 'Grp2','U5','T5' from dual
),
g as
(
select distinct grp, regexp_substr(team,'[^,]+',1,level) team1
from t
connect by level <= LENGTH(REGEXP_REPLACE(team, '[^,]+')) + 1
--group by grp
)
select grp,listagg(team1,',') within group (order by team1) from g
group by grp;
THis is the output I got
+----+-------------------------------------------+
|GRP ||Teams
+----+-------------------------------------------+
|Grp1|T1,T2,T3,T4 |
|Grp2|T2,T4,T5 |
+----+-------------------------------------------+

SQL Server: rows to columns

sample datas
date | num | name | value
01012012 | 1 | A | 20
01012012 | 1 | B | 30
01012012 | 2 | C | 40
wish to like this
date | num | A | B | C
01012012 | 1 | 20 | 30 | --
01012012 | 2 | -- | -- | 40
name is not fixed can allow many names
How about something like
DECLARE #Table TABLE(
date DATETIME,
num INT,
name VARCHAR(20),
value FLOAT
)
INSERT INTO #Table SELECT '20121201',1,'A',20
INSERT INTO #Table SELECT '20121201',1,'B',30
INSERT INTO #Table SELECT '20121201',2,'C',40
SELECT *
FROM (
SELECT date,
num,
name,
value
FROM #Table
) t
PIVOT (
SUM(Value) FOR name IN ([A],[B],[C])
) p
SQL Fiddle DEMO
For dynamic columns you need to use dynamic SQL
SQL FIDDLE EXAMPLE
declare
#cols nvarchar(max),
#stmt nvarchar(max)
select #cols = isnull(#cols + ', ', '') + '[' + Name + ']' from table1
select #stmt = '
select *
from table1 as T
pivot
(
max(T.value)
for name in (' + #cols + ')
) as P'
exec sp_executesql #stmt = #stmt
If you don't need a dynamic number of columns, you can use plain SQL like
select *
from table1 as T
pivot
(
max(T.value)
for name in ([A],[B],[C])
) as P