SQL Matrix to array - sql

I am working with T-SQL and I have a table that looks like Matrix (8x8).
My objective is to make that Matrix (table) into array using Pivot ... I have read forums and more stuff that i managed to find but i still can't make a code for it ...
ID Bucket B1 B2 B3 B4
5 1 20 21 45 12
6 2 12 18 19 48
7 3 19 78 40 78
8 4 72 34 12 17
So all I need to do is to make "three dimensional array" from that table, and to save row, column and value ... to be something like this
Row Column Value
1 1 20
1 2 21
1 3 45
1 2 12
etc
etc
etc
4 3 12
4 4 17
Does anyone have any idea how I could write that code in T-SQL?
ps. Reason i'm doing this, is because i want to multiply my matrix with itself. So it's easier to multiply it if i have it in pivot table.
Thank you

Try unpivoting your data :
DECLARE #table TABLE (id INT, Bucket INT, B1 INT, B2 INT, B3 INT, B4 INT)
INSERT INTO #table VALUES
(5,1,20,21,45,12),
(6,2,12,18,19,48),
(7,3,19,78,40,78),
(8,4,72,34,12,17)
SELECT rn AS [ROW],
VALUE AS [ColumnNumber],
orders AS [VALUE]
FROM
(
SELECT ROW_NUMBER () OVER (ORDER BY id) AS rn,id, Bucket, B1 [1], B2 [2], B3 [3], B4 [4]
FROM #table
) AS t
UNPIVOT
(
orders
FOR VALUE IN([1], [2],[3],[4])
) AS pvt
Check this MSDN Doc for more details of PIVOT and UNPIVOT.

Why use PIVOT? You can get the data out with a simple SELECT query, unless I am missing something here?
DECLARE #Matrix TABLE (
Id INT,
Bucket INT,
B1 INT,
B2 INT,
B3 INT,
B4 INT);
INSERT INTO #Matrix VALUES (5, 1, 20, 21, 45, 12);
INSERT INTO #Matrix VALUES (6, 2, 12, 18, 19, 48);
INSERT INTO #Matrix VALUES (7, 3, 19, 78, 40, 78);
INSERT INTO #Matrix VALUES (8, 4, 72, 34, 12, 17);
SELECT
Bucket AS [Row],
1 AS [Column],
B1 AS Value
FROM
#Matrix
UNION ALL
SELECT
Bucket AS [Row],
2 AS [Column],
B2 AS Value
FROM
#Matrix
UNION ALL
SELECT
Bucket AS [Row],
3 AS [Column],
B3 AS Value
FROM
#Matrix
UNION ALL
SELECT
Bucket AS [Row],
4 AS [Column],
B4 AS Value
FROM
#Matrix
ORDER BY
1, 2;
Results:
Row Column Value
1 1 20
1 2 21
1 3 45
1 4 12
2 1 12
2 2 18
2 3 19
2 4 48
3 1 19
3 2 78
3 3 40
3 4 78
4 1 72
4 2 34
4 3 12
4 4 17

Related

Combine the result set from both tables based on inno

I have a table1 with following structure and data:
header type agrid inno stallno
0 D 14 001 000
0 D 14 008 000
0 N 14 008 000
Another table with following structure and data:
header type agrid inno stallno
1 NULL 14 001 000
1 NULL 14 008 000
How can I achieve the below result set: I tried row_number it works for couple of data sets it doesn't work for other
header type agrid inno
0 D 14 001
1 NULL 14 001
0 D 14 008
1 NULL 14 008
0 N 14 008
1 NULL 14 008
I tried row_number but worked only for couple of agrid's and didn't work for other.
I think you need to build two queries, one for table 1 and one for table 2, then union them together using the row_number and the header value to order them.
create table table1 (header bit, [type] char(1), agrid int, inno int, stallno int);
create table table2 (header bit, [type] char(1), agrid int, inno int, stallno int);
insert into table1 (header, [type], agrid, inno, stallno)
values
(0, 'D', 14, 001, 000),
(0, 'D', 14, 008, 000),
(0, 'N', 14, 008, 000);
insert into table2 (header, [type], agrid, inno, stallno)
values
(1, null, 14, 001, 000),
(1, null, 14, 008, 000);
select t1.*, row_number() over (order by t1.type, t1.inno) rn
from table1 t1
union all
select t2.*, row_number() over (order by t1.type, t1.inno) rn
from table1 t1
inner join table2 t2 on t2.inno = t1.inno
order by rn, header;
Returns
header
type
agrid
inno
stallno
rn
0
D
14
1
0
1
1
null
14
1
0
1
0
D
14
8
0
2
1
null
14
8
0
2
0
N
14
8
0
3
1
null
14
8
0
3
fiddle
Note: For future reference, please take the time to ensure your question is clear and easy to understand. And please create the DDL+DML (as I have shown here) so that people who wish to answer don't have to type your sample data in.

Split space separated values

I have many records like this
ID Tag Arr
1 A 87 34 92
2 A 34 35 38
3 A 39 88 92
4 B 24 49 39
5 B 38 88 23
6 C 39 37 99
I want the end result to look like this in a fast way
Tag Arr No
A 87 1
A 34 2
A 92 2
A 35 1
A 38 1
A 39 1
A 88 1
B 24 1
B 49 1
B 39 1
B 38 1
B 88 1
B 23 1
C 39 1
C 37 1
C 99 1
This is the query i built so far
SELECT DISTINCT T2.tag,
SUBSTRING(
(
SELECT ','+T1.Arr AS [text()]
FROM Tags T1
WHERE T1.tag = T2.tag
and filename = 1
and tag not in ('U')
ORDER BY T1.tag
FOR XML PATH ('')
), 2, 1000) [Ts]
FROM Tags T2
WHERE filename = 1
and tag not in ('U')
You can try this using STRING_SPLIT (Transact-SQL)
which works for SQL Server 2016 and later.
create table tblSampleValue(Id int, Tag Varchar(10), Arr Varchar(50))
insert into tblSampleValue Values
(1, 'A', '87 34 92'),
(2, 'A', '34 35 38'),
(3, 'A', '39 88 92'),
(4, 'B', '24 49 39'),
(5, 'B', '38 88 23'),
(6, 'C', '39 37 99')
Select * from tblSampleValue
select id
, Tag
, [value] as Arr
from tblSampleValue
cross apply string_split(Arr,' ')
Live db<>fiddle demo.
First, you need to use Split function to split Arr column with space.
CREATE FUNCTION udf_Split
( #Words nvarchar(MAX)
, #splitStr varchar(50)
)
RETURNS #Result_Table TABLE
(
[word] nvarchar(max) NULL
)
BEGIN
Declare #TempStr nvarchar(MAX)
WHILE (CHARINDEX(#splitStr,#Words)>0)
BEGIN
Set #TempStr=SUBSTRING(#Words,1,CHARINDEX(#splitStr,#Words)-1)
Insert into #Result_Table (word) Values (#TempStr)
Set #Words = REPLACE(#Words,#TempStr+#splitStr,'')
END/*End While*/
IF(LEN(RTRIM(LTRIM(#Words)))>0 And CHARINDEX(#splitStr,RTRIM(LTRIM(#Words)))=0)
Begin
Set #TempStr=#Words
Insert into #Result_Table (word) Values (#TempStr)
End /*End IF*/
RETURN
END
then use CROSS APPLY with Arr column
SELECT Tag,
word,
count(*) [no]
FROM Tags CROSS APPLY udf_Split(Arr,' ') v
GROUP BY Tag,
word
ORDER BY Tag
sqlfiddle
Note:
if your SQL server version higher than 2016 there is an official function you can use STRING_SPLIT

To create a column Summing the values from another column in the same view

View:
A | B
10 1
15 2
12 3
5 2
2 1
2 1
Output View:
A | B | C
10 1 14
15 2 20
12 3 12
5 2 20
2 1 14
2 1 14
I need to sum the values from column A based on column B. So, all the values from column B having value 1 extract values from column A and then sum it to column C.
I don't see the point, but:
SELECT t.a
,t.b
,sumtab.c
FROM [yourtable] t
INNER JOIN (
SELECT t.b
,sum(t.a) AS C
FROM [yourtable] t
GROUP BY t.b
) AS sumtab
ON t.b = sumtab.b
You could use SUM() OVER like this
DECLARE #SampleData AS TABLE
(
A int,
B int
)
INSERT INTO #SampleData
(
A,
B
)
VALUES
( 10, 1),
( 15, 2),
( 12, 3),
( 5 , 2),
( 2 , 1),
( 2 , 1)
SELECT *,
sum(sd.A) OVER(PARTITION BY sd.B) AS C
FROM #SampleData sd
Returns
A B C
-----------
10 1 14
2 1 14
2 1 14
15 2 20
5 2 20
12 3 12

how to get the summation of column in the last row

select csm.csmCustomerName, cur.curNameOfCurrency,
sum(sot.sotItemTotalAmount)as 'TotalItemsAmount',
SUM(sorTotalTaxAmountValue) as 'TotalTax',
SUM(sorTotalChargeDetailsAmountValue) as 'TotalCharges',
(sum(sorTotalTaxAmountValue)+sum(sorTotalChargeDetailsAmountValue)+sum(sot.sotItemTotalAmount)) as 'NetAmount'
from dbo.SalesOrder sor join dbo.Currency cur
on sor.sorCurrencyId=cur.curId
join dbo.CustomerMaster csm
on sor.sorCustomerMasterId=csm.csmId
join SalesOrderItemDetails sot
on sot.sotSalesOrderId=sor.sorId
Group by csmCustomerName, curNameOfCurrency with rollup;
I want the sum of TotalItemsAmount, TotalTax, TotalCharges and NetAmount in the last row of respective columns.
In result set, I get duplication of each row, could anyone correct the mistake in my code.
C1 C2 C3 C4 C5 C6
A USD 1 7 2 10
B USD 3 6 3 12
C USD 5 3 0 8
D USD 4 2 1 7
13 18 6 37
It is done via the grouping sets like:
DECLARE #t TABLE ( code CHAR(3), a INT, b INT )
INSERT INTO #t
VALUES ( 'USD', 1, 2 ),
( 'USD', 5, 1 ),
( 'USD', 10, 7 ),
( 'EUR', 15, 13 )
SELECT code ,
SUM(a) AS a ,
SUM(b) AS b
FROM #t
GROUP BY GROUPING SETS(( code ), ( ))
Output:
code a b
EUR 15 13
USD 16 10
NULL 31 23

table join where

Table1 t10 (id)
id
---
1
2
table t11(a1,a2,a3)
a1 a2 a3
----------
1 10 a
1 10 b
1 11 b
1 12 c
2 20 d
2 21 e
select * from t10 a,t11 b where a.id = b.a1
how to display
id a1 a2 a3
--------------
1 1 10 a
1 1 10 b //(not display this row)
1 1 11 b //(not display this row)
1 1 12 c //(not display this row)
2 2 20 d
2 2 21 e //(not display this row)
just get t11's random row
maybe display this
id a1 a2
----------
1 1 11 b
1 1 10 a //(not display this row)
1 1 10 b //(not display this row)
1 1 12 c //(not display this row)
2 2 20
2 2 21 //(not display this row)
select a1 as id, a1, min(a2) as a2
from t11
group by a1
will give you:
id a1 a2
----------
1 1 10
2 2 20
This seems almost like he wants something like FIRST/LAST from ms access.
This can ben done (very closely) in Sql Server using
DECLARE #Table TABLE(
id INT,
a1 INT,
a2 INT
)
INSERT INTO #Table (id,a1,a2) SELECT 1, 1, 11
INSERT INTO #Table (id,a1,a2) SELECT 1, 1, 10
INSERT INTO #Table (id,a1,a2) SELECT 1, 1, 12
INSERT INTO #Table (id,a1,a2) SELECT 2, 2, 20
INSERT INTO #Table (id,a1,a2) SELECT 2, 2, 21
SELECT *
FROM #Table t
WHERE a2 = (SELECT TOP 1 a2 FROM #Table WHERE id = t.id AND a1 = t.a1)
This is the answer:
SELECT *
FROM t10 a, (
SELECT * FROM (
SELECT b.*, ROW_NUMBER() OVER(PARTITION BY a10 ORDER BY a10) as rn
FROM t11 b
) WHERE rn =1) b
WHERE a.id = b.a10(+)