SQL Server : transpose multiple columns [duplicate] - sql-server

This question already has answers here:
SQL Server : Transpose rows to columns
(5 answers)
Closed 7 years ago.
What's the best way to get from this input to output?
Input:
date id name info price qty
-----------------------------------------------
20140523 10036 ABC B 12 100
20140523 10036 ABC S 13 75
20140523 10034 XYZ B 22 56
20140523 10034 XYZ S 24 41
20151023 10037 PQR B 30 45
20151023 10037 PQR S 5 20
Output:
date id name b_price b_qty s_price s_qty
---------------------------------------------------------
20140523 10036 ABC 12 100 13 75
20140523 10034 XYZ 22 56 24 41
20140523 10037 PQR 30 45 5 20

With conditional aggregation:
select date,
id,
name,
sum(case info = 'b' then price end) as bprice,
sum(case info = 'b' then qty end) as bqty,
sum(case info = 's' then price end) as sprice,
sum(case info = 's' then qty end) as sqty
from tablename
group by date, id, name

Related

SQL - Select non repeating columns

I have a table like
id name R_id mgr_id
----------------------------
61 a 22 1
62 a 22 2
62 b 23 1
63 c 24 4
63 b 22 3
64 c 25 3
and I would like to get the following result set
R_id mgr_id
--------------
22 1
23 1
24 4
25 3
I would like select repeating R_ids only once
I tried using this query but with not much success, can anyone help me.
SELECT DISTINCT R_id, mgr_id from DT
Perhaps something like this... WITH TIES clause in concert with Row_NUmber()
Example
Select Top 1 with ties
R_ID
,mgr_id
From #YourTable
Order By Row_Number() over (Partition By R_ID order by Mgr_id)
Returns
R_ID mgr_id
22 1
23 1
24 4
25 3

Postgresql select top 5 marks rows for every unique student id

This is one of my views called xyz:
ID | NAME |......Other Data... | Marks
1 A 100
1 A 100
1 A 99
1 A 95
1 A 94
1 A 94
1 A 94
1 A 91
1 A 87
1 A 86
2 B 100
2 B 94
2 B 93
2 B 90
2 B 89
2 B 89
2 B 87
2 B 86
3 C 100
3 C 98
3 C 98
3 C 97
3 C 92
3 C 91
3 C 90
The query I used to get this is something like this:
create or replace view xyz as
select *
from abc
where id in
(select id
from data)
order by id, mark desc, id;
And based on unique ids I want the top 5 rows:
ID | NAME |......Other Data... | Marks
1 A 100
1 A 100
1 A 99
1 A 95
1 A 94
2 B 100
2 B 94
2 B 93
2 B 90
2 B 89
3 C 100
3 C 98
3 C 98
3 C 97
3 C 92
I tried referring to this:
MySQL: Select top 5 rows based on ID and find Subtotal
But I wasn't able to do it. Could you please help?
You can use a windowed rank(), partitioned by each student name, and ordered by marks descending, to find the top 5 marks for each Student:
WITH cteRankedMarks AS
(
SELECT "ID", "NAME", "Marks",
rank() OVER (PARTITION BY "NAME"
ORDER BY "Marks" DESC) AS rank
FROM MyTable
)
SELECT "ID", "NAME", "Marks"
FROM cteRankedMarks
WHERE rank <= 5
ORDER BY "NAME", "Marks" DESC;
SqlFiddle here
Notes
If two or more marks have the same value vying for 5th place, then , then rank will return all such marks. If you don't want ties, then use row_number() instead of rank(). More about these here
Obviously, if a student doesn't have 5 marks, then fewer rows will be returned.

How to pull consecutive months data in sql server even if there is null value

I'm newbie trying to create a SQL query to find how much each Theater has sold the tickets per month during previous year (i.e. for all 12 months). If the collection amount is null or blank I need to produce an output as Zero of any such given month in that year.
I have two tables as below mentioned:
TABLE 1:
Month_Number Year
1 2016
2 2016
3 2016
4 2016
5 2016
6 2016
7 2016
8 2016
9 2016
10 2016
11 2016
12 2016
TABLE 2:
Theater month Amount_In_Thousands
ABC 1 165
ABC 3 70
ABC 4 102
GHI 1 45
GHI 2 70
GHI 3 42
GHI 4 57
ABC 6 122
ABC 7 67
ABC 8 22
ABC 9 80
ABC 11 46
ABC 12 38
You might have noticed for 'ABC' Theater there is 0 or null values for month 2, month 5 and month 10. I am unable to produce these missing months with zero value. I tried with simple left outer join but still the data output row doesn't show with month/year and zero value.
I need to produce the output as below:
OUTPUT
Movie_Theators Month Amount_In_Thounds
ABC 1 165
ABC 2 0 *
ABC 3 70
ABC 4 102
ABC 5 0 *
ABC 6 122
ABC 7 67
ABC 8 22
ABC 9 80
ABC 10 0 *
ABC 11 46
ABC 12 38
GHI 1 45
GHI 2 70
GHI 3 42
GHI 4 57
Can anybody please help me how to write sql script in order to produce the output as shown above. Thank you so much in advance.
You can use a CROSS JOIN between every theater and month-year, and then perform a LEFT JOIN with Table2:
SELECT A.Theater,
B.Month_Number,
B.[Year],
ISNULL(C.Amount_In_Thousands,0) Amount_In_Thousands
FROM ( SELECT DISTINCT Theater
FROM dbo.Table2) A -- or use a dbo.Theater table if you have one
CROSS JOIN dbo.Table1 B
LEFT JOIN dbo.Table2 C
ON A.Theater = C.Theater
AND B.Month_Number = C.[month]
AND B.[Year] = C.[Year];

Spliting one row of record into multiple between two date

Can anybody help me out to do this:
My table data is like
Datefiled Field1 Field2 Field2 Field4
01-01-2012 ABC 10 15 17
01-04-2013 PQR 7 80 65
01-05-2014 XYZ 15 25 77
The output would look something like this
Month/Year Field1 Field2 Field2 Field4
01/2012 ABC 10 15 17
02/2012 ABC 10 15 17
03/2012 ABC 10 15 17
04/2012 ABC 10 15 17
.....
03/2013 ABC 10 15 17
04/2013 PQR 7 80 65
05/2013 PQR 7 80 65
06/2013 PQR 7 80 65
07/2013 PQR 7 80 65
.......
04/2014 PQR 7 80 65
05/2014 XYZ 15 25 77
Just create a calendar table, either one row per day or one row per month, and you can use a tally table (=virtual, constructed for example with a CTE) too and do something like this:
select
*
from
calendar c
cross apply (
select top 1 *
from yourtable y
where y.Datefiled < c.calendardate
order by Datefiled desc
) y
;WITH datat as (
SELECT *
FROM (VALUES
('2012-01-01', 'ABC', 10, 15, 17),('2012-12-12', 'LKJ', 16, 12, 13),
('2013-01-15', 'CVB', 16, 11, 19),('2013-04-01', 'PQR', 7, 80, 65),
('2014-04-24', 'XYZ', 15, 25, 77),('2014-05-17', 'DEF', 12, 40, 50)
) as t(Datefiled, Field1, Field2, Field3, Field4)
), cte AS (
SELECT CAST(MIN(Datefiled) AS DATE) as date_,
CAST(MAX(Datefiled) AS DATE) AS maxd
FROM datat
UNION ALL
SELECT DATEADD(day,1,date_), maxd
FROM cte
WHERE date_ < maxd
)
SELECT CAST([Month] as nvarchar(2)) + '/' + CAST([Year] as nvarchar(4)) as [Month/Year],
Field1,
Field2,
Field3,
Field4
FROM (
SELECT DISTINCT
MONTH(date_) as [Month],
YEAR(date_) as [Year],
Field1,
Field2,
Field3,
Field4
FROM cte c
LEFT JOIN (
SELECT TOP 1 WITH TIES CAST(DATEADD(MONTH, DATEDIFF(MONTH, 0, d1.Datefiled ), 0) as date) as [DateStart],
CAST(DATEADD(MILLISECOND, -3, DATEADD(MONTH, DATEDIFF(MONTH, 0, d2.Datefiled), 0)) as date) as [DateEnd],
d1.Field1,
d1.Field2,
d1.Field3,
d1.Field4
FROM datat d1
LEFT JOIN datat d2
ON d1.Datefiled < d2.Datefiled
ORDER BY ROW_NUMBER() OVER (PARTITION BY d1.Datefiled ORDER BY d2.Datefiled)
) as d
ON c.date_ between d.[DateStart] and ISNULL(d.[DateEnd],c.date_)
WHERE Field1 IS NOT NULL
) as t
ORDER BY [Year], [Month]
OPTION (MAXRECURSION 0)
Output:
Month/Year Field1 Field2 Field3 Field4
---------- ------ ----------- ----------- -----------
1/2012 ABC 10 15 17
2/2012 ABC 10 15 17
3/2012 ABC 10 15 17
4/2012 ABC 10 15 17
5/2012 ABC 10 15 17
6/2012 ABC 10 15 17
7/2012 ABC 10 15 17
8/2012 ABC 10 15 17
9/2012 ABC 10 15 17
10/2012 ABC 10 15 17
11/2012 ABC 10 15 17
12/2012 LKJ 16 12 13
1/2013 CVB 16 11 19
2/2013 CVB 16 11 19
3/2013 CVB 16 11 19
4/2013 PQR 7 80 65
5/2013 PQR 7 80 65
6/2013 PQR 7 80 65
7/2013 PQR 7 80 65
8/2013 PQR 7 80 65
9/2013 PQR 7 80 65
10/2013 PQR 7 80 65
11/2013 PQR 7 80 65
12/2013 PQR 7 80 65
1/2014 PQR 7 80 65
2/2014 PQR 7 80 65
3/2014 PQR 7 80 65
4/2014 XYZ 15 25 77
5/2014 DEF 12 40 50
(29 row(s) affected)

Transpose Rows to Columns for the same ID

I have table called equipment.
Unit_ID SensorSerial 1
11 1
22
1 33
2
44 2
55 2
66 3
77 3
88 3
99
I would like to make query to have following table:
Unit_ID Sensor1 Sensor2
Sensor3 1
11
22
33 2
44
55
66 3
77
88
99
You can try this
select Unit_ID,
max(case when seqnum = 1 then SensorSerial end) as Sensor1,
max(case when seqnum = 2 then SensorSerial end) as Sensor2,
max(case when seqnum = 3 then SensorSerial end) as Sensor3
from (select equipment.*,
row_number() over (partition by Unit_ID order by SensorSerial) as seqnum
from equipment
) equipment
group by Unit_ID;

Resources