MS SQL copy data from another table by rows - sql-server

I have following 2 tables:
DECLARE #table1 TABLE (
[NO] int,
A1 float,
A2 float,
A3 float,
A4 float,
A5 float,
A6 float
)
DECLARE #table2 TABLE (
KOD nvarchar(100),
ID_QUANTITY int
)
INSERT INTO #table1 VALUES
(1, 4.1, 3, 3.5, 23.5, 12.2, 2.4),
(2, 4.2, 0, 1.9, 34.5, 31.2, 34.2),
(3, 1.5, 0, 2.3, 12.3, 12.3, 1.2),
(4, 3.7, 2.1, 5.9, 4.8, 10.2, 21.2),
(5, 3.9, 2.6, 1.9, 12.3, 2.4, 10.2)
INSERT INTO #table2 VALUES
('A1', 500),
('A2', 600),
('A3', 700),
('A4', 800),
('A5', 900),
('A6', 1000)
And I need create script in sql for transform value in first table to appearance as below
Thank you for your help

UNPIVOT then JOIN, use ROW_NUMBER() for ID column:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as ID,
ID_QUANTITY,
[VALUES]
FROM (
SELECT *
FROM table1
) p
UNPIVOT (
[VALUES] FOR [COL] IN (A1,A2,A3,A4,A5,A6)
) as unpvt
LEFT JOIN table2 t
ON t.KOD = unpvt.[COL]
ORDER BY ID_QUANTITY, [NO]
Output:
ID ID_QUANTITY VALUES
1 500 4,1
2 500 4,2
3 500 1,5
4 500 3,7
5 500 3,9
6 600 3
7 600 0
8 600 0
9 600 2,1
10 600 2,6
...
25 900 2,4
26 1000 2,4
27 1000 34,2
28 1000 1,2
29 1000 21,2
30 1000 10,2

Use UNPIVOT
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
t2.ID_Quantity,
t1.Value
FROM Table2 t2
INNER JOIN
(
SELECT *
FROM Table1
UNPIVOT
(
[Values] FOR [Columns] IN ([A1], [A2],[A3], [A4], [A5],[A6])
) as pvt
) t1
ON t1.Columns = t2.KOD

try this :
create table3(ID_QUANTITY int(11),VALUE int(11));
for($i=1;$i<6;$i++){
$insert=mysql_query("insert into table3 select a.ID_QUANTITY,b.A$i from table2 a,table1 b where a.KOD='A$i');
}

Related

Add incrementally row values of a column of type string

I have a table with the following values
UserID ParentID Levels Path
1 NULL 0 A1
5 1 1 A2
9 5 2 A3
43 9 3 A4
The output should be like followed :
UserID ParentID Levels FinalPath
1 NULL 0 A1/
5 1 1 A1/A2/
9 5 2 A1/A2/A3/
43 9 3 A1/A2/A3/A4/
Thanks in advance for any guidance on this.
Solution using a recusive common table expression.
Sample data
create table users
(
userid int,
parentid int,
levels int,
path nvarchar(100)
);
insert into users (userid, parentid, levels, path) values
(1, NULL, 0, 'A1'),
(5, 1, 1, 'A2'),
(9, 5, 2, 'A3'),
(43, 9, 3, 'A4');
Solution
with cte as
(
select u.userid, u.parentid, u.levels, u.path
from users u
where u.parentid is null
union all
select u.userid, u.parentid, u.levels, convert(nvarchar(100), c.path + '/' + u.path)
from users u
join cte c
on c.userid = u.parentid
)
select c.userid, c.parentid, c.levels, c.path + '/' as FinalPath
from cte c;
Fiddle
Here's a version that both calculates the Level and appends the Path.
Data
drop table if exists dbo.test_table;
go
create table dbo.test_table(
UserID int,
ParentID int,
[Path] varchar(5));
insert dbo.test_table([UserID], [ParentID], [Path]) values
(1,null, 'A1'),
(5,1, 'A2'),
(9,5, 'A3'),
(43,9, 'A4');
Query
;with recur_cte([UserId], [ParentID], h_level, [Path]) as (
select [UserId], [ParentID], 0, cast([Path] as varchar(100))
from dbo.test_table
where [ParentID] is null
union all
select tt.[UserId], tt.[ParentID], rc.h_level+1, cast(concat(tt.[Path], '/', rc.[Path]) as varchar(100))
from dbo.test_table tt join recur_cte rc on tt.[ParentID]=rc.[UserId])
select * from recur_cte;
Results
UserId ParentID h_level Path
1 NULL 0 A1
5 1 1 A1/A2
9 5 2 A1/A2/A3
43 9 3 A1/A2/A3/A4

A Different kind of transformation of data in sql

I'm looking for a query were i can derive a new column based on columns values as shown below in example
P X Y Z A B C
1 1.1 2.1 1.3 1 Null 3
2 Null 1.4 3.1 2 4.7 1
3 2.2 Null 4.6 4 3.5 1
4 Null 1.8 3.4 2 1.7 4
Which i want to show as shown below;
P Group X y Z A B C
1 Xgrp 1.1 - - - - -
1 Ygrp - 2.1 - - - -
1 Zgrp 1.3 - - -
1 Agrp 1
1 Bgrp Null
1 Cgrp 3
Please help me :)
Regards
Andy
I am not sure how you are defining these dashes, so they are ignored in the code below. There is some additional logic in the ORDER BY clause in order to show the results like in your example. Basically, we are performing UNPIVOT to define the group values and then performing again PIVOT:
DECLARE #DataSource TABLE
(
[P] TINYINT
,[X] DECIMAL(9,1)
,[Y] DECIMAL(9,1)
,[Z] DECIMAL(9,1)
,[A] DECIMAL(9,1)
,[B] DECIMAL(9,1)
,[C] DECIMAL(9,1)
);
INSERT INTO #DataSource ([P], [X], [Y], [Z], [A], [B], [C])
VALUES (1, 1.1, 2.1, 1.3, 1, NULL, 3)
,(2, NULL, 1.4, 3.1, 2, 4.7, 1)
,(3, 2.2, NULL, 4.6, 4, 3.5, 1 )
,(4, NULL, 1.8, 3.4, 2, 1.7, 4);
SELECT *
FROM
(
SELECT [P]
,[value]
,[column]
,[column] + 'grp'
FROM #DataSource
UNPIVOT
(
[value] FOR [column] IN ([X], [Y], [Z], [A], [B], [C])
) UNPVT
) DS ([P], [value], [column], [group])
PIVOT
(
MAX([value]) FOR [column] IN ([X], [Y], [Z], [A], [B], [C])
) PVT
ORDER BY [P]
,CASE [group]
WHEN 'Xgrp' THEN 1
WHEN 'Ygrp' THEN 2
WHEN 'Zgrp' THEN 3
WHEN 'Agrp' THEN 4
WHEN 'Bgrp' THEN 5
WHEN 'Cgrp' THEN 6
END
What gotqn posted is missing some rows - specifically ones where all columns should be NULL (such as the "Bgrp" record where P=1).
You can get what you're looking for without PIVOT or UNPIVOT, just a simple CROSS JOIN, GROUP BY and CASE statement like so:
-- sample data
DECLARE #DataSource TABLE
(
[P] TINYINT
,[X] DECIMAL(9,1)
,[Y] DECIMAL(9,1)
,[Z] DECIMAL(9,1)
,[A] DECIMAL(9,1)
,[B] DECIMAL(9,1)
,[C] DECIMAL(9,1)
);
INSERT INTO #DataSource ([P], [X], [Y], [Z], [A], [B], [C])
VALUES (1, 1.1, 2.1, 1.3, 1, NULL, 3)
,(2, NULL, 1.4, 3.1, 2, 4.7, 1)
,(3, 2.2, NULL, 4.6, 4, 3.5, 1 )
,(4, NULL, 1.8, 3.4, 2, 1.7, 4);
-- solution
SELECT
p, [group],
X = CASE [group] WHEN 'Xgrp' THEN MAX(X) END,
Y = CASE [group] WHEN 'Ygrp' THEN MAX(Y) END,
Z = CASE [group] WHEN 'Zgrp' THEN MAX(Z) END,
A = CASE [group] WHEN 'Agrp' THEN MAX(A) END,
B = CASE [group] WHEN 'Bgrp' THEN MAX(B) END,
C = CASE [group] WHEN 'Cgrp' THEN MAX(C) END
FROM (VALUES ('Xgrp'),('Ygrp'),('Zgrp'),('Agrp'),('Bgrp'),('Cgrp')) groups([group])
CROSS JOIN #DataSource d
GROUP BY p, [group]
-- Uncomment this ORDER BY for testing:
--ORDER BY [P]
-- ,CASE [group]
-- WHEN 'Xgrp' THEN 1
-- WHEN 'Ygrp' THEN 2
-- WHEN 'Zgrp' THEN 3
-- WHEN 'Agrp' THEN 4
-- WHEN 'Bgrp' THEN 5
-- WHEN 'Cgrp' THEN 6
-- END;
Results

How to create a Matrix table on SQL from another table

I have the following table with the following columns.
-------------------------------------
Column1 | Column2 | TotalCount
--------------------------------------
1 1 40
1 2 50
2 1 10
2 2 60
Also, I have another table that is related to Column1 where 1 is X and 2 is Y and same for Column2 where 1 is A and 2 is B
I am trying to come up with a SQL statement that basically gives me some view like...
--------------------
ColumnName | A | B
--------------------
X 40 50
Y 10 60
Any idea how can I achieve that? I've been trying to pivot the data with no luck.
Thanks!
Full working example:
DECLARE #DataSource TABLE
(
[Column1] TINYINT
,[Column2] TINYINT
,[TotalCount] TINYINT
);
INSERT INTO #DataSource ([Column1], [Column2], [TotalCount])
VALUES (1, 1, 40)
,(1, 2, 50)
,(2, 1, 10)
,(2, 2, 60);
SELECT *
FROM
(
SELECT IIF([Column1] = 1, 'X', 'Y') AS [ColumnName]
,IIF([Column2] = 1, 'A', 'B') AS [Column2]
,[TotalCount]
FROM #DataSource
) DS
PIVOT
(
MAX([TotalCount]) FOR [Column2] IN ([A], [B])
) PVT;
Using conditional aggregation:
WITH tbl AS(
SELECT * FROM ( VALUES
(1, 1, 40), (1, 2, 50),
(2, 1, 10), (2, 2, 60)
)t(Column1, Column2, TotalCount)
)
SELECT
ColumnName = CASE WHEN Column1 = 1 THEN 'X' ELSE 'Y' END,
A = MAX(CASE WHEN Column2 = 1 THEN TotalCount END),
B = MAX(CASE WHEN Column2 = 2 THEN TotalCount END)
FROM tbl
GROUP BY Column1
RESULT:
ColumnName A B
---------- ----------- -----------
X 40 50
Y 10 60

Unpivot table data

Sno Water Milk
1 50 100
2 22 120
3 11 142
i have this table.Now i want result like
Sno Type Qnty
1 Water 83
2 Milk 362
How can I please tell me.
SQL Server 2008 does not support this kind of statement.
You can achieve that in 2 ways:
using temporary table (variable type table)
DECLARE #products TABLE(Sno INT, Water INT, Milk INT)
INSERT INTO #products
VALUES (1, 50, 100), (2, 22, 120), (3, 11, 142)
SELECT ROW_NUMBER() OVER(ORDER BY SUM(Qnty)) AS RowNo, Product, SUM(Qnty) AS Qnty
FROM (
SELECT Product, Qnty
FROM (
SELECT *
FROM #products
) AS pvt
UNPIVOT (Qnty FOR Product IN ([Water],[Milk])) AS unpvt
) AS T
GROUP BY Product</pre>
or
;WITH T AS
(
SELECT Sno, Water, Milk
FROM (
SELECT 1 AS Sno, 50 AS Water, 100 AS Milk
UNION ALL
SELECT 2, 22, 120
UNION ALL
SELECT 3, 11, 142
) t (Sno, Water, Milk))
SELECT Sno = ROW_NUMBER() OVER(ORDER BY SUM(Upvt.Qnty)),
upvt.Type,
Qnty = SUM(Upvt.Qnty)
FROM T
UNPIVOT
( Qnty
FOR Type IN ([Water], [Milk])
) upvt
GROUP BY upvt.Type
ORDER BY Qnty;</pre>
Please,refer MSDN documentation.
The first step is to UNPIVOT your data:
WITH T AS
( SELECT Sno, Water, Milk
FROM (VALUES (1, 50, 100), (2, 22, 120), (3, 11, 142)) t (Sno, Water, Milk)
)
SELECT upvt.Sno,
upvt.Type,
Upvt.Qnty
FROM T
UNPIVOT
( Qnty
FOR Type IN ([Water], [Milk])
) AS upvt;
Which will give:
Sno Type Qnty
1 Water 50
1 Milk 100
2 Water 22
2 Milk 120
3 Water 11
3 Milk 142
You can then apply normal aggregation to this result:
WITH T AS
( SELECT Sno, Water, Milk
FROM (VALUES (1, 50, 100), (2, 22, 120), (3, 11, 142)) t (Sno, Water, Milk)
)
SELECT Sno = ROW_NUMBER() OVER(ORDER BY SUM(Upvt.Qnty)),
upvt.Type,
Qnty = SUM(Upvt.Qnty)
FROM T
UNPIVOT
( Qnty
FOR Type IN ([Water], [Milk])
) AS upvt
GROUP BY upvt.Type
ORDER BY Qnty;
Giving:
Sno Type Qnty
1 Water 83
2 Milk 362
EDIT
Based on your comment that you are using SQL Server 2005, not 2008 as indicated below is a full working example that will work on 2005:
DECLARE #T TABLE (Sno INT, Water INT, Milk INT);
INSERT #T (Sno, Water, Milk) VALUES (1, 50, 100);
INSERT #T (Sno, Water, Milk) VALUES(2, 22, 120);
INSERT #T (Sno, Water, Milk) VALUES(3, 11, 142);
SELECT Sno = ROW_NUMBER() OVER(ORDER BY SUM(Upvt.Qnty)),
upvt.Type,
Qnty = SUM(Upvt.Qnty)
FROM #T AS T
UNPIVOT
( Qnty
FOR Type IN ([Water], [Milk])
) AS upvt
GROUP BY upvt.Type
ORDER BY Qnty;
It was the table valued constructor I was using to create the sample data that was causing the error in 2005, nothing to do with the actual query that unpivots then sums the data.
This gives the result you asked for but I get the idea you want something a little more advanced. If so please elaborate.
SELECT 'water', sum(water) FROM table_name
UNION ALL
SELECT 'milk', sum(milk) FROM table_name

How to find the parent ID in a return table

I have following table:
ID ParentID
1 NULL
2 1
3 2
4 NULL
5 4
6 5
7 3
I want to find the first ID of a specific child ID.
Example: ID=7 and the result is 1
ID=6 and the result is 4
How to do it?
You need to do a bit of recursive CTE magic to solve this one.
Given the data in a table variable thusly:
declare #data table(id int, parentid int)
insert into #data
select 1, null
union select 2,1
union select 3,2
union select 4, null
union select 5,4
union select 6,5
union select 7,3
The following should do the trick:
;with recursiveTable as
(
select d.id, d.parentId, 0 as depth
from #data d
where d.id=6 -- Parameterize this
union all
select d.id, d.parentid, r.depth-1
from #data d
inner join recursiveTable r
on d.id = r.parentId
)
select top 1 id
from recursiveTable
order by depth
Plugging 6 in as above returns 4. Changing this to 7 returns 1 as requested.
Try this:
CREATE TABLE childpar(ID int,ParentID int)
INSERT INTO childpar
values(1,NULL),
(2, 1),
(3, 2),
(4, NULL),
(5, 4),
(6, 5),
(7, 3)
DECLARE #inpyID int
SET #inpyID=7
;WITH CTE1 as (
select * from childpar where id=#inpyID
union all
select c2.* from CTE1 c1 inner join childpar c2 on c1.ParentID = c2.ID
)
select top 1 id from CTE1 order by id asc

Resources