Rearranging a table in tsql - sql-server

So I have a table with the following columns:
Type Test Min Max
-----------------------------
1 a 1 2
1 b Null Null
2 a 0 Null
2 b Null 1
Trying to get all of them like this
Type Test1 Test1 min Test1max Test2 Test2min Test2max
------------------------------------------------------------
1 a 1 2 b Null Null
2 a 0 Null b Null 1
Tried using unpivot first before I use pivot but it's still giving duplicate tests and removing null any help with this is much appreciated
Need null values to show up as well
Select type, result
(
From
Select type, min
From table t
)
Unpivot
(result for minmax in (min1)
)
Select
Thanks

using row_number() and conditional aggregation:
select
[Type]
, Test_1 = max(case when rn = 1 then Test end)
, Test_1_Min = max(case when rn = 1 then Min end)
, Test_1_Max = max(case when rn = 1 then Max end)
, Test_2 = max(case when rn = 2 then Test end)
, Test_2_Min = max(case when rn = 2 then Min end)
, Test_2_Max = max(case when rn = 2 then Max end)
from (
select *
, rn = row_number() over (partition by [Type] order by [Test])
from t
) as s
group by s.Type
rextester demo: http://rextester.com/BKL48976
returns:
+------+--------+------------+------------+--------+------------+------------+
| Type | Test_1 | Test_1_Min | Test_1_Max | Test_2 | Test_2_Min | Test_2_Max |
+------+--------+------------+------------+--------+------------+------------+
| 1 | a | 1 | 2 | b | NULL | NULL |
| 2 | a | 0 | NULL | b | NULL | 1 |
+------+--------+------------+------------+--------+------------+------------+

select *
from table t1
join table t2
on t1.type = t2.type
and t1.test < t2.test

Related

SQL server Query for SUM group

I have table:
-------------------------------------
| Code | Name | Type | Qty |
-------------------------------------
| 0001 | Mouse | Purchase | 5 |
| 0002 | KeyBrd | Purchase | 8 |
| 0003 | Mouse | Sale | 2 |
-------------------------------------
i want to select them like this:
------------------------------------------------------------
| Code | Name | Total Purchase | Total Sale | Stock |
------------------------------------------------------------
| 0001 | Mouse | 5 | 2 | 3 |
| 0002 | KeyBrd | 8 | 0 | 8 |
------------------------------------------------------------
Im so confused, please help me with the query, thank you in advance
Try This
SELECT
Code,
Name,
TotalPurchase = SUM(CASE WHEN [Type] = 'Purchase' THEN Qty ELSE 0 END),
TotalSale = SUM(CASE WHEN [Type] = 'Sale' THEN Qty ELSE 0 END),
Stock = SUM(CASE WHEN [Type] = 'Purchase' THEN Qty ELSE 0 END) - SUM(CASE WHEN [Type] = 'Sale' THEN Qty ELSE 0 END)
FROM YourTable
group by Code,
Name
Conditional aggregation with the help of case expression is one approach
select min(Code) Code,
Name,
sum(case when Type = 'Purchase' then Qty else 0 end) [Total Purchase],
sum(case when Type = 'Sale' then Qty else 0 end) [Total Sale],
sum(case when Type = 'Purchase' then -Qty else Qty end) Stock
from table t
group by Name
We can also use like below.(Using Pivot) Please try this.
Data Generation
CREATE TABLE TableCase
(
Code VARCHAR(10)
,[Name] VARCHAR(10)
,[Type] VARCHAR(20)
,Qty INT
)
GO
INSERT INTO TableCase VALUES
('0001','Mouse' ,'Purchase',5),
('0002','KeyBrd' ,'Purchase',8),
('0003','Mouse' ,'Sale',2 )
GO
SOLUTION
SELECT MIN(Code) Code,[Name]
, ISNULL(SUM([Purchase]),0) [TotalPurchase]
, ISNULL(SUM([Sale]),0) TotalSale
, ISNULL(SUM([Purchase]),0) - ISNULL(SUM([Sale]),0) Stock
FROM TableCase
PIVOT
(
MAX(Qty) FOR [Type] IN ([Purchase],[Sale])
)t
GROUP By [Name]
ORDER BY [code]
OUTPUT
Code Name TotalPurchase TotalSale Stock
---------- ---------- ------------- ----------- -----------
0001 Mouse 5 2 3
0002 KeyBrd 8 0 8
(2 rows affected)

Convert a (<=4) x 2 SQL result set to 1 x 8 result set

I've spent much too long trying to figure out how TSQL pivoting works, so I'm posting this hoping someone that understands pivots can help me.
So here's a representative source result set:
Notice that there are only 3 rows, but that's still <=4.
| Code | Date |
|-------|------------|
| 12345 | 2018-01-01 |
| 67890 | NULL |
| 13579 | 2018-01-02 |
This is target result set I want from the source result set:
| Code_1 | Date_1 | Code_2 | Date_2 | Code_3 | Date_3 | Code_4 | Date_4 |
|--------|------------|--------|--------|--------|------------|--------|--------|
| 12345 | 2018-01-01 | 67890 | NULL | 13579 | 2018-01-02 | NULL | NULL |
Here's something that does literally what you're asking by joining 2 pivot queries together:
DECLARE #tbl TABLE (code INT, dt DATETIME)
INSERT INTO #tbl VALUES (12345, '1/1/2018')
INSERT INTO #tbl VALUES (67890, null)
INSERT INTO #tbl VALUES (13579, '1/1/2018')
SELECT SQ1.Code_1, SQ2.Code_1, SQ1.Code_2, SQ2.Code_2, SQ1.Code_3, SQ2.Code_3, SQ1.Code_4, SQ2.Code_4
FROM
(
SELECT [Code_1], [Code_2], [Code_3], [Code_4]
FROM
(
SELECT 'Code_' + CAST(ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS VARCHAR(3)) AS RowID, code FROM #tbl
) source
PIVOT
(
MAX(code)
FOR RowID IN ([Code_1], [Code_2], [Code_3], [Code_4])
)sq
)SQ1
CROSS APPLY
(
SELECT [Code_1], [Code_2], [Code_3], [Code_4]
FROM
(
SELECT 'Code_' + CAST(ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS VARCHAR(3)) AS RowID, dt FROM #tbl
) source
PIVOT
(
MAX(dt)
FOR RowID IN ([Code_1], [Code_2], [Code_3], [Code_4])
)sq
)SQ2
Outputs:
Code_1 Code_1 Code_2 Code_2 Code_3 Code_3 Code_4 Code_4
12345 2018-01-01 67890 NULL 13579 2018-01-01 NULL NULL
Assuming you want a max of 4 groups (8 columns).
You may also notice that in the Order By I use (Select null). Without a proper sequence key, there is no gtd of order.
Example
Select Code_1 = max(case when Col=1 then Code end)
,Date_1 = max(case when Col=1 then Date end)
,Code_2 = max(case when Col=2 then Code end)
,Date_2 = max(case when Col=2 then Date end)
,Code_3 = max(case when Col=3 then Code end)
,Date_3 = max(case when Col=3 then Date end)
,Code_4 = max(case when Col=4 then Code end)
,Date_4 = max(case when Col=4 then Date end)
From (
Select *
,Col = Row_Number() over (Order by (Select null))
From #YourTable
) A
Returns
Code_1 Date_1 Code_2 Date_2 Code_3 Date_3 Code_4 Date_4
12345 2018-01-01 67890 NULL 13579 2018-01-01 NULL NULL

SQL pivot to flatten rows into columns

I have a source table that looks like this:
+--------------+----------+------+------------+-----------+
| vehicleindex | parentid | year | make | model |
+--------------+----------+------+------------+-----------+
| 1 | 1 | 2007 | TOYOTA | SIENNA LE |
| 2 | 1 | 2005 | VOLKSWAGEN | JETTA GLS |
+--------------+----------+------+------------+-----------+
I'd like to select from this table such that the output looks like this:
+-------+--------+-----------+-------+------------+-----------+
| year1 | make1 | model1 | year2 | make2 | model2 |
+-------+--------+-----------+-------+------------+-----------+
| 2007 | TOYOTA | SIELLA LE | 2005 | VOLKSWAGEN | JETTA GLS |
+-------+--------+-----------+-------+------------+-----------+
How can I accomplish this on a SQL Server database with a pivot? There will always be either 1 or 2 vehicles in the source table. In the case where there's 1 vehicle, I would expect Year2, Make2 and Model2 to be NULL.
Similar to SQLZim's answer. Only difference is that the Window function Row_Number() is used just in case vehicleindex is not a consistent 1 and 2.
Select year1 = max(case when RN=1 then [year] end)
,make1 = max(case when RN=1 then make end)
,model1 = max(case when RN=1 then model end)
,year2 = max(case when RN=2 then [year] end)
,make2 = max(case when RN=2 then make end)
,model2 = max(case when RN=2 then model end)
From (
Select *
,RN = Row_Number() over (Partition By parentid Order By vehicleindex)
From YourTable
) A
Group By parentid
EDIT: Option 2 - Use PIVOT
Select *
From (
Select parentid
,item = concat(B.item,Dense_Rank() over (Partition By parentid Order By vehicleindex))
,value
From YourTable
Cross Apply ( values ('year' ,cast(Year as varchar(100)))
,('make' ,make)
,('model',model)
) B (item,value)
) A
Pivot (max(value) For [item] in ([year1],[make1],[model1],[year2],[make2],[model2]) ) p
Using conditional aggregation:
select
parentid
, year1 = max(case when vehicleindex=1 then [year] end)
, make1 = max(case when vehicleindex=1 then make end)
, model1 = max(case when vehicleindex=1 then model end)
, year2 = max(case when vehicleindex=2 then [year] end)
, make2 = max(case when vehicleindex=2 then make end)
, model2 = max(case when vehicleindex=2 then model end)
from t
group by parentid
returns:
+----------+-------+------------+-----------+-------+------------+-----------+
| parentid | year1 | make1 | model1 | year2 | make2 | model2 |
+----------+-------+------------+-----------+-------+------------+-----------+
| 1 | 2007 | TOYOTA | SIENNA LE | 2005 | VOLKSWAGEN | JETTA GLS |
| 2 | 2018 | TESLA | MODEL 3 | NULL | NULL | NULL |
+----------+-------+------------+-----------+-------+------------+-----------+
rextestder demo: http://rextester.com/ZTGXU25389
using this test data:
create table t (
vehicleindex int
, parentid int
, [year] int
, make varchar(32)
, model varchar(32)
);
insert into t values
(1,1,2007,'TOYOTA ','SIENNA LE')
, (2,1,2005,'VOLKSWAGEN','JETTA GLS')
, (1,2,2018,'TESLA','MODEL 3')
Unfortunately if you need to pivot 3 columns you need to create 3 separate pivots, then merge them in the end:
SELECT MAX(Year1) as 'Year1', MAX(Make1) as Make1, MAX(Model1) as 'Model1',
MAX(Year2) as 'Year2', MAX(Make2) as Make2, MAX(Model2) as 'Model2'
FROM
(
SELECT parentid,
[1] as 'Year1', NULL as Make1, NULL as 'model1',
[2] as 'Year2', NULL as Make2, NULL as 'model2'
FROM (
SELECT
parentid, vehicleindex, model, make , [year]
FROM #temp
) as s
PIVOT
(
max([year])
FOR vehicleindex IN ([1],[2])
) AS yearPvt
UNION
SELECT parentid,
NULL as 'Year1', [1] as Make1, NULL as 'model1',
NULL as 'Year2', [2] as Make2, NULL as 'model2'
FROM
(
SELECT
parentid, vehicleindex, model, make , [year]
FROM #temp
) as s
parentid, vehicleindex, model, make , [year]
FROM #temp
) as s
PIVOT
(
MAX([make])
FOR vehicleindex IN ([1],[2])
)AS makePvt
UNION
SELECT parentid,
NULL as 'Year1', NULL as Make1, [1] as 'model1',
NULL as 'Year2', NULL as Make2, [2] as 'model2'
FROM
(
SELECT
parentid, vehicleindex, model, make , [year]
FROM #temp
) as s
PIVOT
(
max([model])
FOR vehicleindex IN ([1],[2])
) AS modelPvt
) allPivots
Group BY parentid

Create the summary table SQL

I have a table of product stock (ProductStockTemp):
ProductStockId | ProductCode | ProductName | ProductStockClosingBalance
-------------------------------------------------------------------------
1 | A1 | A2 | 200
2 | B1 | B2 | 0
3 | A1 | A2 | 100
4 | C1 | C2 | -400
5 | B1 | B2 | 700
6 | C1 | C2 | 0
7 | D1 | D2 | 0
8 | D1 | D2 | 0
I would like to create a table like that
ProductCode | ProductName | TypeA | TypeB
------------------------------------------
A1 | A2 | 200 | 100
B1 | B2 | 0 | 700
C1 | C2 | -400 | 0
D1 | D2 | 0 | 0
It means the first product record will be the product type A and the latest record will be the product type B. I think i have to select the latest product record first. However, the problem arises when the product appears one time then it will choose this record. In this case, I want the product type B will be 0 since the first will be the product type A and the latest will be the type B. My query to select the latest product record in the table
select
p.ProductCode,
p.ProductName,
p.ProductStockClosingBalance
from
ProductStockTemp p
where
p.ProductStockId = (select MAX(q.ProductStockId)
from ProductStockTemp q
where p.ProductCode = q.ProductCode)
order by
p.ProductCode
I'm really stuck right now!
Most obvius in my opinion for this case:
;with cteStock as
(
select
p.ProductCode,
p.ProductName,
p.ProductStockClosingBalance,
row_number() over(partition by p.ProductCode, p.ProductName order by p.ProductStockId asc) rn_asc,
row_number() over(partition by p.ProductCode, p.ProductName order by p.ProductStockId desc) rn_desc,
from ProductStockTemp p
)
select
s.ProductCode, s.ProductName,
sum(case when s.rn_asc = 1 then s.ProductStockClosingBalance else 0) as TypeA,
sum(case when s.rn_desc = 1 and s.rn_asc != s.rn_desc then s.ProductStockClosingBalance else 0) as TypeB
from cteStock s
group by s.ProductCode, s.ProductName
but it's no good to have such a denormalized table with no info about period and names stored right here.
s.rn_asc != s.rn_desc - for the case when there is only one row.
Not sure about default zero but it's up to you and your task definition.
I suggest you to learn SQL GROUP BY Statement
SELECT ProductCode, ProductName, min(ProductStockClosingBalance) as TypeA, Max(ProductStockClosingBalance) as TypeB
FROM ProductStockTemp p
GROUP BY ProductCode, ProductName
This query does what you want.
declare #prod table(ProductStockId int, ProductCode varchar(10), ProductName varchar(10), ProductStockClosingBalance int)
insert #prod values
( 1 , 'A1' , 'A2' , 200),
( 2 , 'B1' , 'B2' , 0),
( 3 , 'A1' , 'A2' , 100),
( 4 , 'C1' , 'C2' , -400),
( 5 , 'B1' , 'B2' , 700),
( 6 , 'C1' , 'C2' , 0),
( 7 , 'D1' , 'D2' , 0),
( 8 , 'D1' , 'D2' , 0 )
;with prod as(
select *
,ROW_NUMBER() over(partition by productcode order by ProductStockId) rn1
,ROW_NUMBER() over(partition by productcode order by ProductStockId desc) rn2
from #prod
)
select productcode,ProductName,
(select ProductStockClosingBalance from prod p1 where p.productcode=p1.ProductCode and p1.rn1=1) TypeA,
ProductStockClosingBalance typeB
from prod p
where rn2=1
Results:
productcode ProductName TypeA typeB
A1 A2 200 100
B1 B2 0 700
C1 C2 -400 0
D1 D2 0 0
use below query
;With ctef as (select ProductCode , ProductName , ProductStockClosingBalance
row_number()over(partition by ProductCode , ProductName ordered by ProductStockId asc) as r from ProductStock)
, ctef1 as ( select * from ctef where r =1)
, ctel as (select ProductCode , ProductName , ProductStockClosingBalance
row_number()over(partition by ProductCode , ProductName ordered by ProductStockId desc)as r2 from ProductStock )
, ctel1 as ( select * from ctel where r =1)
select f.ProductCode , f.ProductName ,f.ProductStockClosingBalance as typea ,nullif(l.ProductStockClosingBalance ,f.ProductStockClosingBalance ) as typeB
from ctef1 f left join ctel1 s
on f.ProductCode =s.ProductCode and f.ProductName =s.ProductName
if using sql servere 2012 or above Analytic Functions FIRST_VALUE (Transact-SQL) and LAST_VALUE (Transact-SQL) can be used .

SQL SERVER How to combine two query on the same table that has "group by"

I want to combine two queries on the same table that has group by.
here is my table :
Date##### | Value1 | Value2 | Value3 | Type
23/04/2014 | 1,2 | 12,3 | 10 | Green
23/04/2014 | 11,2 | 3 | 10,3 | Non-Green
24/04/2014 | 10,9 | 3 | 11 | Green
24/04/2014 | 2,3 | 12,3 | 8 | Green
25/04/2014 | 10 | 2 | 10,8 | Non-Green
25/04/2014 | 1,4 | 5 | 12 | Green
I want it to display:
Date##### | Count |Type
23/04/2014 | 2 | Green
23/04/2014 | 2 | Non-Green
24/04/2014 | 3 | Green
25/04/2014 | 2 | Non-Green
25/04/2014 | 1 | Green
here is my first query :
Dim strCommand As String = "SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN ManualAssists1 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists2 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth where Type = 'Green' GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC"
It display :
Date##### | Count |Type
23/04/2014 | 2 | Green
24/04/2014 | 3 | Green
25/04/2014 | 1 | Green
my second query :
Dim strCommand As String = "SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN ManualAssists1 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists2 >= 10 THEN 1 ELSE 0 END + CASE WHEN ManualAssists3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth where Type = 'Non-Green' GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC"
It display :
Date##### | Count |Type
23/04/2014 | 2 | Non-Green
25/04/2014 | 2 | Non-Green
I want to combine both query to become one, and take the date, result of green and result of non-green. Assume that I have a lot of group of date, I want it to display only the last 7 group of date based on ASC order. I try to add UNION between my two query. Here is my code so far:
Dim strCommand As String = "Select 'Test1', * from tbBooth where type ='Green' and exist(SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC) Union Select 'Test2', * from tbBooth where type ='Non-Green' and exist(SELECT d, LW, cnt FROM(SELECT TOP 7 [date] AS d, [Type] as LW, SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END + CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt FROM tbBooth GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC)
it give me an error Incorrect syntax near the keyword 'SELECT'.
is ther anyway how to do it? I tried to look on other SO post but I don't have any clue to do it because both my query are complex...
Thanks in advances....
It's not that your combined query is complex, it's just that it's wrong.
What I don't understand is why you have the WHERE Type = 'Green' and 'Non-green'.
Given what you want as result, you could just remove that where and get pretty much what you're after:
SELECT d ,
LW ,
cnt
FROM ( SELECT TOP 7
[date] AS d ,
[Type] AS LW ,
SUM(CASE WHEN ManualAssists1 >= 10 THEN 1
ELSE 0
END + CASE WHEN ManualAssists2 >= 10 THEN 1
ELSE 0
END + CASE WHEN ManualAssists3 >= 10 THEN 1
ELSE 0
END) AS cnt
FROM tbBooth
--WHERE Type = 'Green'
GROUP BY [date] ,
[Type]
ORDER BY [date] DESC
) x
ORDER BY d ASC
Which gives:
2014-04-23 Green 2
2014-04-23 Non-Green 2
2014-04-24 Green 3
2014-04-25 Green 1
2014-04-25 Non-Green 2
I see no need to "combine" the two queries when the two queries are identical besides the 'Type' in the WHERE?
Bro, in your code change exist to exists
:) this should Work
Updated:
Add Top 7 to select
Select 'Test1', * from tbBooth
where type ='Green' and exists(SELECT **top 7** d, LW, cnt FROM(SELECT TOP 7 [date] AS d,
[Type] as LW,
SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt
FROM tbBooth GROUP BY [date],[Type]
ORDER BY [date] DESC) x ORDER BY d ASC)
Union
Select 'Test2', * from tbBooth where type ='Non-Green'
and exists(SELECT **top 7** d, LW, cnt FROM(SELECT TOP 7
[date] AS d, [Type] as LW, SUM(CASE WHEN Value1 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value2 >= 10 THEN 1 ELSE 0 END
+ CASE WHEN Value3 >= 10 THEN 1 ELSE 0 END) AS cnt
FROM tbBooth GROUP BY [date],[Type] ORDER BY [date] DESC) x ORDER BY d ASC)

Resources