SQL Unpivot multiple columns Data - sql

I am using SQL server 2008 and I am trying to unpivot the data. Here is the SQL code that I am using,
CREATE TABLE #pvt1 (VendorID int, Sa int, Emp1 int,Sa1 int,Emp2 int)
GO
INSERT INTO #pvt1 VALUES (1,2,4,3,9);
GO
--Unpivot the table.
SELECT distinct VendorID,Orders,Orders1
FROM
(SELECT VendorID, Emp1, Sa,Emp2,Sa1
FROM #pvt1 ) p
UNPIVOT
(Orders FOR Emp IN
(Emp1,Emp2)
)AS unpvt
UNPIVOT
(Orders1 FOR Emp1 IN
(Sa,Sa1)
)AS unpvt1;
GO
And Here is the result of the above code.
VendorID Orders Orders1
1 4 2
1 4 3
1 9 2
1 9 3
But I want my Output to be the way indicated below
VendorID Orders Orders1
1 4 2
1 9 3
The relationship from the above code is 2 is related to 4, and 3 is related to 9.
How can I achieve this?

An easier way to unpivot the data would be to use a CROSS APPLY to unpivot the columns in pairs:
select vendorid, orders, orders1
from pvt1
cross apply
(
select emp1, sa union all
select emp2, sa1
) c (orders, orders1);
See SQL Fiddle with Demo. Or you can use CROSS APPLY with the VALUES clause if you don't want to use the UNION ALL:
select vendorid, orders, orders1
from pvt1
cross apply
(
values
(emp1, sa),
(emp2, sa1)
) c (orders, orders1);
See SQL Fiddle with Demo

The answer by Taryn is indeed super useful, and I'd like to expand one aspect of it.
If you have a very un-normalized table like this, with multiple sets of columns for e.g. 4 quarters or 12 months:
+-------+------+------+------+------+------+------+-------+------+
| cYear | foo1 | foo2 | foo3 | foo4 | bar1 | bar2 | bar3 | bar4 |
+-------+------+------+------+------+------+------+-------+------+
| 2020 | 42 | 888 | 0 | 33 | one | two | three | four |
+-------+------+------+------+------+------+------+-------+------+
Then the CROSS APPLY method is easy to write and understand, when you got the hang of it. For the numbered column, use constant values.
SELECT
cYear,
cQuarter,
foo,
bar
FROM temp
CROSS APPLY
(
VALUES
(1, foo1, bar1),
(2, foo2, bar2),
(3, foo3, bar3),
(4, foo4, bar4)
) c (cQuarter, foo, bar)
Result:
+-------+----------+-----+-------+
| cYear | cQuarter | foo | bar |
+-------+----------+-----+-------+
| 2020 | 1 | 42 | one |
| 2020 | 2 | 888 | two |
| 2020 | 3 | 0 | three |
| 2020 | 4 | 33 | four |
+-------+----------+-----+-------+
SQL Fiddle

I needed composit key AND skip extras row in case when data is missing (NULLs). For ex. when x2 and y2 are possible replacement vendor and price
WITH pvt AS (SELECT * FROM (VALUES
( 1, 6, 11, 111, 12, 13, 122, 133),
( 2, 6, 21, 211, 22, 23, 222, 233),
( 3, 6, 31, 311, 32, 33, 322, 333),
( 5, 4, 41, 411, 42, NULL, 422, NULL),
( 6, 4, 51, 511, 52, NULL, 522, NULL))
s( id, s, a, b, x1, x2, y1, y2)
)
-- SELECT * FROM pvt
SELECT CONCAT('xy_',s,'_', id, postfix) as comp_id, a, b, x, y
FROM pvt
CROSS APPLY
(
VALUES
(NULL, x1, y1),
('_ext', x2, y2)
) c (postfix, x, y)
WHERE x IS NOT NULL
produces
comp_id a b x y
-------------------------------- ----------- ----------- ----------- -----------
xy_6_1 11 111 12 122
xy_6_1_ext 11 111 13 133
xy_6_2 21 211 22 222
xy_6_2_ext 21 211 23 233
xy_6_3 31 311 32 322
xy_6_3_ext 31 311 33 333
xy_4_5 41 411 42 422
xy_4_6 51 511 52 522
(8 rows affected)
from:
id s a b x1 x2 y1 y2
----------- ----------- ----------- ----------- ----------- ----------- ----------- -----------
1 6 11 111 12 13 122 133
2 6 21 211 22 23 222 233
3 6 31 311 32 33 322 333
5 4 41 411 42 NULL 422 NULL
6 4 51 511 52 NULL 522 NULL
(5 rows affected)

Related

SQL - How Cumulative Sum when group by values are missing

As a follow-up to my previous ticket - which I now believe the example was too simple (previous question), I prepared an example of a scenario where I'm looking to aggregate column cus_sum group on the date_col column and the cus column representing the unique customer number.
I wish to generate a series of dates for instance (function generate series) from the 1st of January 2018 till the 10th of January 2018 and then have a cumulative sum of column cus_sum for each customer. As in the case below, you can imagine that there are days without information at all and days where not all customers have any records - regardless i want to show their cumulative sum throughout that period.
CREATE TABLE test2 (date_col date, cus int, cus_sum int);
insert into test2 values ('2018-01-01', 1, 5);
insert into test2 values ('2018-01-02', 1, 12);
insert into test2 values ('2018-01-02', 2, 14);
insert into test2 values ('2018-01-03', 2, 8);
insert into test2 values ('2018-01-03', 2, 10);
insert into test2 values ('2018-01-04', 1, 22);
insert into test2 values ('2018-01-06', 2, 20);
insert into test2 values ('2018-01-06', 1, 5);
insert into test2 values ('2018-01-07', 1, 45);
insert into test2 values ('2018-01-08', 2, 32);
The output should look like:
date_col cus cum_sum
"2018-01-01" 1 5
"2018-01-01" 2 0
"2018-01-02" 1 17
"2018-01-02" 2 14
"2018-01-03" 1 17
"2018-01-03" 2 32
"2018-01-04" 1 39
"2018-01-04" 2 32
"2018-01-05" 1 39
"2018-01-05" 2 32
"2018-01-06" 1 89
"2018-01-06" 2 52
"2018-01-07" 1 134
"2018-01-07" 2 52
"2018-01-08" 1 134
"2018-01-08" 1 84
Perhaps I should add that - one table I assume will be a virtual table that generates a list of dates in a given timeframe. The second table is a list of customers[1,3,4,5..10], products purchases (product volume) - which is what I wish to cumulative sum for every customer and everyday of the series.
Assuming that you have separate table for customers, so you can use CTE to generate the data range and then join croos join customer table to have all combinations of customer and dates, then you get the sum from test2 table. the query will look like below -
WITH DateRange AS (
SELECT
[MyDate] = CONVERT(DATETIME,'01/01/2018')
UNION ALL
SELECT
[MyDate] = DATEADD(DAY, 1, [Date])
FROM
DateRange
WHERE
[MyDate] <= '01/10/2018'
) SELECT
d.[MyDate]
c.cus
(
select isnull(sum(cus_sume),0)
from test2 t
where t.date = d.mydate
and c.cust = t.cust
) as cus_sum
FROM
DateRange d
cross join customer c
order by d.MyDate
The cross join of generate_series() and unnest() creates a virtual table of all possible values:
select distinct
date_col::date,
cus,
coalesce(sum(cus_sum) over (partition by cus order by date_col), 0) as cum_sum
from generate_series('2018-01-01'::date, '2018-01-08', '1d') as date_col
cross join (select distinct cus from test2) c
left join test2 using (date_col, cus)
order by date_col, cus
date_col | cus | cum_sum
------------+-----+---------
2018-01-01 | 1 | 5
2018-01-01 | 2 | 0
2018-01-02 | 1 | 17
2018-01-02 | 2 | 14
2018-01-03 | 1 | 17
2018-01-03 | 2 | 32
2018-01-04 | 1 | 39
2018-01-04 | 2 | 32
2018-01-05 | 1 | 39
2018-01-05 | 2 | 32
2018-01-06 | 1 | 44
2018-01-06 | 2 | 52
2018-01-07 | 1 | 89
2018-01-07 | 2 | 52
2018-01-08 | 1 | 89
2018-01-08 | 2 | 84
(16 rows)
It looks like there are mistakes in the OP's expected results.
DbFiddle.

how to divide the columns in result of query in oracle database

want to split the columns in result of query dynamically, how can i?
i have three tables and joined them.to get the required columns.
select distinct t1.sal,t1.cat,t2.id,t3.shop
from t_table1 t1,
t_table2 t2,
t_table3 t3,
where t1.sno=t2.sno AND
t2.cat=t3.cat
t3.dept_no=t3.dept_no
**output:**
t1.sal t1.cat t2.id t3.shop
1900 34R5 10 dense
1900 34r5 10 SVM
1900 34r5 10 bpo
2345 3ER4 11 kpo
2345 3ER4 11 infra
12345 34F4 12 const
**desired output:**
t1.sal t1.cat t1.tin t2.id t3.shop_1 t3.shop_2 t3.shop_3
1900 34r5 23456 10 dense svm bpo
2345 3er4 6543 11 kpo infra null
12345 34f4 34556 12 const null null
Use a PIVOT and the ROW_NUMBER analytic function:
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE your_query_result (sal, cat, id, shop ) AS
SELECT 1900, '34R5', 10, 'dense' FROM DUAL UNION ALL
SELECT 1900, '34r5', 10, 'SVM' FROM DUAL UNION ALL
SELECT 1900, '34r5', 10, 'bpo' FROM DUAL UNION ALL
SELECT 2345, '3ER4', 11, 'kpo' FROM DUAL UNION ALL
SELECT 2345, '3ER4', 11, 'infra' FROM DUAL UNION ALL
SELECT 12345, '34F4', 12, 'const' FROM DUAL;
Query 1:
SELECT sal,
cat,
id,
"1_SHOP" AS shop_1,
"2_SHOP" AS shop_2,
"3_SHOP" AS shop_3
FROM (
SELECT r.*,
ROW_NUMBER() OVER (
PARTITION BY sal, cat, id
ORDER BY shop
) AS rn
FROM (
SELECT * FROM your_query_result
) r
)
PIVOT (
MAX( shop ) AS shop
FOR rn IN ( 1, 2, 3 )
)
Results:
| SAL | CAT | ID | SHOP_1 | SHOP_2 | SHOP_3 |
|-------|------|----|--------|--------|--------|
| 1900 | 34R5 | 10 | dense | (null) | (null) |
| 1900 | 34r5 | 10 | SVM | bpo | (null) |
| 2345 | 3ER4 | 11 | infra | kpo | (null) |
| 12345 | 34F4 | 12 | const | (null) | (null) |
If you want the first and second rows on the same line then just change the CAT column to be in lower-case before generating the ROW_NUMBER and PIVOTing.

Getting the column name that holds the maximum value of a row

I have generated an extensive view which simulates certain occurrences based on different statistic models. These models are defined in each column header by a number and the maximum value of a row is the best model.
The table generated looks (partially) as follows;
+--------+----+------+------+------+------+------+------+
| Number | LI | PHSE | 0505 | 0506 | 0507 | 0508 | 0509 | [...] etc.
+--------+----+------+------+------+------+------+------+
| 100254 | 2 | M1 | 44 | 46 | 45 | 44 | 44 |
| 100254 | 2 | M2 | 36 | 36 | 35 | 37 | 37 |
| 100254 | 2 | M3 | 5 | 5 | 5 | 5 | 5 |
| 100254 | 2 | R1 | 34 | 36 | 37 | 37 | 37 |
| 100254 | 2 | R2 | 41 | 41 | 40 | 41 | 41 |
| 100329 | 1 | M1 | 37 | 38 | 38 | 38 | 39 |
| 100329 | 1 | M2 | 31 | 29 | 28 | 29 | 29 |
| 100329 | 1 | M3 | 6 | 6 | 6 | 6 | 6 |
| 100329 | 1 | R1 | 29 | 29 | 29 | 30 | 30 |
| 100329 | 1 | R2 | 25 | 26 | 26 | 27 | 26 |
+--------+----+------+------+------+------+------+------+
[...] etc.
Now I want to find the highest value in each row and display the corresponding column name as such;
| Number | LI | PHSE | MAXCOL |
+--------+----+------+--------+
| 100254 | 2 | M1 | 0506 |
| 100254 | 2 | M2 | 0508 |
| 100254 | 2 | M3 | 0505 |
| 100254 | 2 | R1 | 0507 |
| 100254 | 2 | R2 | 0505 |
+--------+----+------+--------+
[...] etc.
This is derived from 100254 - 2 - M1 largest value 46 occurring in column 0506, etc.
I've been toying around with PIVOT functions but no success there. I've also looked for an Index/Match equivalent like in Excel but since I can't refer to column headers as values this obviously won't work (and haven't found such function either).
Any help would be hugely appreciated.
UPDATE per Damien's comment:
An excerpt from the code that led to this:
SELECT DISTINCT sub2.Number, sub2.LI, sub2.PHSE
, sum(sub2.[0505]) over (partition by sub2.Number, sub2.LI, sub2.PHSE) as '0505'
, sum(sub2.[0506]) over (partition by sub2.Number, sub2.LI, sub2.PHSE) as '0506'
[...] etc. /*64 rows*/
FROM
(SELECT DISTINCT sub.*
, CASE WHEN sub.MF > sub.[5PAV] - sub.[5PSTDEV] THEN 1 ELSE 0 END AS '0505'
, CASE WHEN sub.MF > sub.[5PAV] - sub.[6PSTDEV] THEN 1 ELSE 0 END AS '0506'
[...] etc. /*64 rows*/
FROM
(SELECT DISTINCT ra.*
, sum(ra.qtyr) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 5 preceding AND 1 preceding) /
sum(ra.qtyu) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 5 preceding AND 1 preceding) AS '5PAV'
, sum(ra.qtyr) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 6 preceding AND 1 preceding) /
sum(ra.qtyu) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 6 preceding AND 1 preceding) AS '6PAV'
[...] etc. /*8 rows*/
, stdev(ra.MF) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 4 preceding AND CURRENT row) AS '5PSTDEV'
, stdev(ra.MF) OVER (partition BY ra.Number, ra.LI, ra.PHSE ORDER BY (ra.Number) rows BETWEEN 5 preceding AND CURRENT row) AS '6PSTDEV'
[...] etc. /*8 rows*/
FROM ra
) AS sub
) AS sub2
No doubt that this may be one of the most ineffective uses of SQL, but time-pressure and inexperience made me write it this way.
Any suggestions to change this code and achieve the desired table result more efficiently would be much appreciated too.
EDIT per Anton's answer;
The above code summarized as pvt continues as follows;
SELECT Number, LI, PHSE, combo, hitrate
FROM (...) AS pvt
UNPIVOT
(Hitrate FOR Combo IN (
[0505],
[0506],
[...] etc.)) AS upvt
Great solution to an inelegant problem.
You need to use UNPIVOT, not PIVOT
https://msdn.microsoft.com/en-us/library/ms177410.aspx
If the number of columns is variable, you have to use dynamic sql to construct the list of columns
If you want to see all MAXCOL (equal columns) try this:
CREATE TABLE table1 (
Number NUMERIC(10),
LI numeric(10),
PHSE NVARCHAR(10),
[0505] numeric(10),
[0506] numeric(10),
[0507] numeric(10),
[0508] numeric(10),
[0509] numeric(10))
INSERT INTO table1 VALUES(100254,2,'M1',44 ,46 ,45 ,44,44)
INSERT INTO table1 VALUES(100254,2,'M2',36,36,35,37,37)
INSERT INTO table1 VALUES(100254,2,'M3',5,5,5,5,5)
INSERT INTO table1 VALUES(100254,2,'R1',34,36,37,37,37)
INSERT INTO table1 VALUES(100254,2, 'R2',41,41,40,41,41)
INSERT INTO table1 VALUES(100329,1, 'M1',37,38,38,38,39)
INSERT INTO table1 VALUES(100329,1, 'M2',31,29,28,29,29)
INSERT INTO table1 VALUES(100329,1, 'M3',6,6,6,6,6)
INSERT INTO table1 VALUES(100329,1, 'R1',29,29,29,30,30)
INSERT INTO table1 VALUES(100329,1, 'R2',25,26,26,27,26)
SELECT *
INTO #UNPIVOT
FROM table1
UNPIVOT ( num
FOR MAXCOL IN ([0505],[0506],[0507],[0508],[0509])) AS k
SELECT A.Number,A.LI,A.PHSE,A.num,B.MAXCOL FROM
(SELECT number,LI,PHSE,MAX(num) AS num FROM #UNPIVOT GROUP BY number,LI,PHSE) A
LEFT JOIN
(SELECT * FROM #UNPIVOT) B ON A.num=B.num AND A.Number=B.Number AND A.LI=B.LI AND A.PHSE=B.PHSE
I would use CROSS APPLY as follows:
WITH Src AS
(
SELECT * FROM (VALUES
(100254, 2, 'M1', 44, 46, 45, 44, 44),
(100254, 2, 'M2', 36, 36, 35, 37, 37),
(100254, 2, 'M3', 5, 5, 5, 5, 5),
(100254, 2, 'R1', 34, 36, 37, 37, 37),
(100254, 2, 'R2', 41, 41, 40, 41, 41),
(100329, 1, 'M1', 37, 38, 38, 38, 39),
(100329, 1, 'M2', 31, 29, 28, 29, 29),
(100329, 1, 'M3', 6, 6, 6, 6, 6),
(100329, 1, 'R1', 29, 29, 29, 30, 30),
(100329, 1, 'R2', 25, 26, 26, 27, 26)) T(Number, LI, PHSE, [0505], [0506], [0507], [0508], [0509])
)
SELECT Number, LI, PHSE, MaxCol
FROM Src
CROSS APPLY (SELECT TOP 1 * FROM (VALUES
('0505', [0505]),
('0506', [0506]),
('0507', [0507]),
('0508', [0508]),
('0509', [0509])
) T(MaxCol, Val) ORDER BY Val DESC) Q
Note that equal columns may be chosen randomly unless some additional value is specified, i.e. MaxCol.
Update
You need dynamic query, like following one:
DECLARE #sql nvarchar(MAX) =
'SELECT Number, LI, PHSE, MaxCol
FROM Src
CROSS APPLY (SELECT TOP 1 * FROM (VALUES' +STUFF(
(SELECT ',(', QUOTENAME(name, '''')+','+QUOTENAME(name)+')'
FROM sys.columns
WHERE object_id=OBJECT_ID('Src') AND name NOT IN ('Number', 'LI', 'PHSE')
FOR XML PATH('')), 1, 1, '')+') T(MaxCol, Val) ORDER BY Val DESC) Q';
EXEC(#sql);
Src is your table name, replace it accordingly.
You can use UNPIVOT and CROSS APPLY.
With this solution you don't have to specify all the columns multiple times.
Source data:
CREATE TABLE Student
([Name] varchar(5), [Maths] int, [Science] int, [English] int)
;
INSERT INTO Student
([Name], [Maths], [Science], [English])
VALUES
('Tilak', 90, 40, 60),
('Raj', 30, 50, 70)
;
Solution:
with foo as (
select name, subject, marks
from student
unpivot
(
marks
for subject in (Science, Maths, English)
) u
)
select distinct f1.name, f2.subject
from foo f1
cross apply (
select top 1 name, subject
from foo
where f1.Name = Name
order by Marks desc) f2
Result:
--------------------------------------------------
| Name | Subject
--------------------------------------------------
| Tilak | Maths
--------------------------------------------------
| Raj | Science
--------------------------------------------------
http://sqlfiddle.com/#!18/780cd8/5

Empty column values but keep values equal to the number provided using SQL Query

Suppose the following table
ID Name RowNumber
2314 YY 1
213 XH 2
421 XD 3
123 AA 4
213 QQQ 5
12 WW 6
312 RR 7
123 GG 8
12 F 9
12 FF 10
312 VV 11
12 BB 12
32 NN 13
43 DD 14
53 DD 15
658 QQQQ 16
768 GGG 17
I want to replace the Name field with empty string based on condition that
First and Last cells value will not be removed.
Need to return values not in continuous cells.
Only n number of cells will be preserved
if n is less than or equal to the number entered by user than do nothing
For example, if user enters 5 then only 5 values will be preserved and the result should be (OR similar)-
ID Name RowNumber
2314 YY 1
213 2
421 3
123 AA 4
213 5
12 6
312 7
123 GG 8
12 9
12 10
312 11
12 12
32 NN 13
43 14
53 15
658 16
768 GGG 17
There could be more records than this.
I'm using SQL Server
The following will work in SQL Server 2012+, because it uses running/cumulative SUM. The query assumes that values in RowNumber column are sequential from 1 to total row count without gaps. If your data is not like this, you can use ROW_NUMBER to generate them.
Calculate Ratio of the given number N and total number of rows (CTE_Ratio)
Calculate running sum of this Ratio, truncating the fractional part of the sum (CTE_Groups)
Each integer value of the running rum defines a group of rows, re-number rows within each group (CTE_Final)
Preserve Name only for the first row from each group
To understand better how it works include intermediate columns (Ratio, GroupNumber, rn) into the output
SQL Fiddle
Sample data
DECLARE #T TABLE ([ID] int, [Name] varchar(50), [RowNumber] int);
INSERT INTO #T([ID], [Name], [RowNumber]) VALUES
(2314, 'YY', 1)
,(213, 'XH', 2)
,(421, 'XD', 3)
,(123, 'AA', 4)
,(213, 'QQQ', 5)
,(12, 'WW', 6)
,(312, 'RR', 7)
,(123, 'GG', 8)
,(12, 'F', 9)
,(12, 'FF', 10)
,(312, 'VV', 11)
,(12, 'BB', 12)
,(32, 'NN', 13)
,(43, 'DD', 14)
,(53, 'DD', 15)
,(658, 'QQQQ', 16)
,(768, 'GGG', 17);
DECLARE #N int = 5;
Query
WITH
CTE_Ratio AS
(
SELECT
ID
,Name
,RowNumber
,COUNT(*) OVER() AS TotalRows
,CAST(#N-1 AS float) / CAST(COUNT(*) OVER() AS float) AS Ratio
FROM #T
)
,CTE_Groups AS
(
SELECT
ID
,Name
,RowNumber
,TotalRows
,ROUND(SUM(Ratio) OVER(ORDER BY RowNumber), 0, 1) AS GroupNumber
FROM CTE_Ratio
)
,CTE_Final AS
(
SELECT
ID
,Name
,RowNumber
,TotalRows
,ROW_NUMBER() OVER(PARTITION BY GroupNumber ORDER BY RowNumber) AS rn
FROM CTE_Groups
)
SELECT
ID
,CASE WHEN rn=1 OR RowNumber = TotalRows THEN Name ELSE '' END AS Name
,RowNumber
FROM CTE_Final
ORDER BY RowNumber;
Result
+------+------+-----------+
| ID | Name | RowNumber |
+------+------+-----------+
| 2314 | YY | 1 |
| 213 | | 2 |
| 421 | | 3 |
| 123 | | 4 |
| 213 | QQQ | 5 |
| 12 | | 6 |
| 312 | | 7 |
| 123 | | 8 |
| 12 | F | 9 |
| 12 | | 10 |
| 312 | | 11 |
| 12 | | 12 |
| 32 | NN | 13 |
| 43 | | 14 |
| 53 | | 15 |
| 658 | | 16 |
| 768 | GGG | 17 |
+------+------+-----------+
Try this:
--Number that user enter
DECLARE #InputNumber INT
DECLARE #WorkingNumber INT
DECLARE #TotalRecords INT
DECLARE #Devider INT
SET #InputNumber = 5
SET #WorkingNumber = #InputNumber -2
--Assume #InputNumber greater than 2 and #TotalRecords greater than 4
SELECT #TotalRecords = COUNT(*)
FROM Table;
SET #Devider = CONVERT(#TotalRecords, DECIMAL(18,2))/CONVERT(#WorkingNumber, DECIMAL(18,2));
WITH Conditioned (RowNumber)
AS
(
SELECT RowNumber
FROM Table
WHERE RowNumber = 1
UNION
SELECT T.RowNumber
FROM (SELECT TOP 1 RowNumber
FROM Conditioned
ORDER BY RowNumber DESC) AS C
INNER JOIN Table AS T ON CONVERT(CEILING(C.RowNumber + #Devider), INT) = T.RowNumber
)
SELECT T.Id, CASE WHEN C.RowNumber IS NULL THEN '' ELSE T.Name END, T.RowNumber
FROM Table T
LEFT OUTER JOIN Conditioned C ON T.RowNumber = C.RowNumber
WHERE
UNION RowNumber != #TotalRecords
SELECT Id, Name, RowNumber
FROM Table
WHERE RowNumber = #TotalRecords

How to insert into separate tables result of aggregate SQL query

I have a table with an index and I am executing a aggregate SQL query using sum
you can see what I am doing here in sqlfiddle.
Create table TX (
i int NOT NULL PRIMARY KEY,
x1 DECIMAL(7,3),
x2 DECIMAL(7,3),
x3 DECIMAL(7,3)
);
INSERT INTO TX (i,x1,x2,x3) values
(1,5, 6,6) ;
INSERT INTO TX (i,x1,x2,x3) values
(2,6, 7, 5);
INSERT INTO TX (i,x1,x2,x3) values
(3,5, 6, 7) ;
INSERT INTO TX (i,x1,x2,x3) values
(4,6, 7, 4);
My question is How can I insert into 3 different tables the results of that query?
SELECT SUM(1),
SUM(x1),SUM(x2),SUM(x3),
SUM(x1*x1),
SUM(x2*x1),SUM(x2*x2),
SUM(x3*x1),SUM(x3*x2),SUM(x3*x3)
FROM TX
so
how can I get something like
Sum(1)
-----
n
index Sums
------------
1 4
2 22
3 26
index1 index2 Mult
----------------------
1 1 122
2 1 144
2 2 170
3 1 119
3 2 141
3 3 126
Instead of
SUM(1) SUM(X1) SUM(X2) SUM(X3) SUM(X1*X1) SUM(X2*X1) SUM(X2*X2) SUM(X3*X1) SUM(X3*X2) SUM(X3*X3)
_____________________________________________________________________________________________________
4 22 26 22 122 144 170 119 141 126
Run 3 separate queries. Turning the SELECTs into INSERTs depends on the RDBMS. For SQL Server, it's just adding an INTO newTableName before the FROM clause to create a new one, or INSERT INTO existingTableName before the SELECT statement.
Create table TX (
i int NOT NULL PRIMARY KEY,
x1 DECIMAL(7,3),
x2 DECIMAL(7,3),
x3 DECIMAL(7,3)
);
INSERT INTO TX (i,x1,x2,x3) values
(1,5, 6,6) ;
INSERT INTO TX (i,x1,x2,x3) values
(2,6, 7, 5);
INSERT INTO TX (i,x1,x2,x3) values
(3,5, 6, 7) ;
INSERT INTO TX (i,x1,x2,x3) values
(4,6, 7, 4);
Query 1:
SELECT COUNT(*) AS SUM1
FROM TX
Results:
| SUM1 |
--------
| 4 |
Query 2:
SELECT SUM(X1) index1, SUM(X2) sums
FROM TX
Results:
| INDEX1 | SUMS |
-----------------
| 22 | 26 |
Query 3:
SELECT x.index1,
x.index2,
case x.id
when 1 then SUM(x1*x1)
when 2 then SUM(x2*x1)
when 3 then SUM(x2*x2)
when 4 then SUM(x3*x1)
when 5 then SUM(x3*x2)
when 6 then SUM(x3*x3)
end Mult
FROM TX
CROSS JOIN
(select 1 id, 1 index1, 1 index2 union all
select 2 id, 2 index1, 1 index2 union all
select 3 id, 3 index1, 1 index2 union all
select 4 id, 2 index1, 2 index2 union all
select 5 id, 3 index1, 2 index2 union all
select 6 id, 3 index1, 3 index2) x
GROUP BY x.id, x.index1, x.index2
ORDER BY x.id
Results:
| INDEX1 | INDEX2 | MULT |
--------------------------
| 1 | 1 | 122 |
| 2 | 1 | 144 |
| 3 | 1 | 170 |
| 2 | 2 | 119 |
| 3 | 2 | 141 |
| 3 | 3 | 126 |
SELECT SUM(1)
FROM TX;
SELECT 1, SUM(x1)
FROM TX
UNION ALL
SELECT 2, SUM(x2)
FROM TX
UNION ALL
SELECT 3, SUM(x3)
FROM TX;
SELECT a.x i1, b.x i2, SUM(a.s * b.s)
FROM
(
SELECT i, 1 x, x1 s
FROM TX
UNION ALL
SELECT i, 2 x, x2 s
FROM TX
UNION ALL
SELECT i, 3 x, x3 s
FROM TX
) a
INNER JOIN
(
SELECT i, 1 x, x1 s
FROM TX
UNION ALL
SELECT i, 2 x, x2 s
FROM TX
UNION ALL
SELECT i, 3 x, x3 s
FROM TX
) b ON a.i = b.i AND a.x >= b.x
GROUP BY a.x, b.x;
SQL Fiddle using your data - Note that your data's sums (second query) do not match those in your question. I trust this is a typo.
Notice I got a bit lazy with the third query. Instead of writing out the expansion I flattened the table first and joined it on itself.
Also note that in the first query SUM(1) can be replaced with COUNT(*).