Query which converts rows into columns - sql

I have something like
ZoneNumber AverageSpeed
1 20
2 30
3 50
4 60
5 70
And I want to have a view like
AverageSpeed 1 AverageSpeed 2 AverageSpeed 3 AverageSpeed 4 AverageSpeed 5
20 30 50 60 70
Does anyone have any ideas what my query need to be written like?

You need to use Pivot.
Pivot rotates a table-valued expression by turning the unique values from one column in the expression into multiple columns in the output, and performs aggregations where they are required on any remaining column values that are wanted in the final output.
Basic example:
SELECT *
FROM (
SELECT year(invoiceDate) as [year], left(datename(month,invoicedate),3) as [month], InvoiceAmount as Amount
FROM Invoice
) as s
PIVOT
(
SUM(Amount)
FOR [month] IN (jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec)
)AS pivot

Related

SQL - create column with row averages excluding null values

I have a table like this
name
jan
feb
march
april
may
stan
3
null
7
null
3
dawn
2
3
9
2
null
and I'd like to ad a column that has averages rows while skipping nulls
name
jan
feb
mar
apr
may
AVG
stan
3
null
7
null
3
4.3
dawn
2
3
9
2
null
4
The following code results in a null value for all rows that are missing values
SELECT *, AVG(jan+feb+mar+apr+may)/5 as avg
FROM t
Thanks in advance!
I would use arrays and then unnest it to calculate the avg
with cte as
(select *, unnest(array[jan,feb,mar,apr,may]) as months
from t)
select name,jan, feb, mar, apr, may, avg(months)
from cte
group by name, jan, feb, mar, apr, may;

How to get data from date

Hi I would like to get data from date for users. I ve got a table with all months but i would like to get how much they earn on month
user
month
money
1
january
10
2
january
1
1
april
100
2
april
1000
1
march
0
2
march
1
And result should be:
user
money_on_april
money_on_march
1
100
0
2
1000
1
3
0
0
Assuming you want a column for every month, or a certain subset of months:
SELECT
user,
SUM(CASE month WHEN 'january' THEN money ELSE 0 END) As money_on_january,
SUM(CASE month WHEN 'february' THEN money ELSE 0 END) As money_on_february,
...
FROM
YourTable
GROUP BY
user
If you only want columns for the months which exist in the table, then you'll need to use dynamic SQL instead.
If you are using MS SQL, Try PIVOT
SELECT * FROM [Your Table]
PIVOT(
SUM([money])
FOR [month] IN ([january],[april],[march])
)pvt

How to use pivot and have 2 different aggregate functions?

I have a table with 1 date column. I want to group the dates by year and month so that I have a matrix such as:
Year Jan Feb Mar...Dec Total
2015.....
2016 10 15 10... 10 115
2017.....
Is this possible to achieve using the PIVOT function, and how exactly do I use it to achieve the above?
You can achieve without PIVOT
SELECT
DATEPART(yyyy,t.the_date) as year,
SUM(CASE WHEN DATEPART(mm,t.the_date)=1 THEN 1 ELSE 0 END) as Jan,
SUM(CASE WHEN DATEPART(mm,t.the_date)=2 THEN 1 ELSE 0 END) as Feb,
...
SUM(CASE WHEN DATEPART(mm,t.the_date)=12 THEN 1 ELSE 0 END) as Dec,
COUNT(*) as Total
FROM the_table t
GROUP BY DATEPART(yyyy,t.the_date)
try using this query : -
SELECT *
FROM (
SELECT
year(yourDate) as [year],left(datename(month,yourDate),3)as [month],
Amount
FROM YourTableName
) as s
PIVOT
(
SUM(Amount)
FOR [month] IN (jan, feb, mar, apr,
may, jun, jul, aug, sep, oct, nov, dec)
)AS pvt

How to maintain a running balance in a month wise report

SELECT *
FROM
(SELECT
YEAR (DateOfTransaction) AS year,
LEFT(DATENAME(MONTH, DateOfTransaction), 3) AS month,
SUM(CASE WHEN TransTypeName LIKE 'credit%' THEN amount ELSE 0 END) -
SUM(CASE WHEN TransTypeName LIKE 'Debit%' THEN amount ELSE 0 END) AS Balance
FROM
.............) AS t
PIVOT (SUM(balance) FOR month IN (jan, feb, march, ...., Dec)) AS pvt
This query returns a month-wise report account balance. I want a result is running balance.
Example:
January month I credit 5000, February month I credit 2000
My query result is
year jan feb march...dec
2014 5000 2000 null ..null
I want a result like this:
year jan feb march...dec
2014 5000 7000 null ..null
(5000+2000)
Try this
SELECT year,Jan = Jan, Feb = isnull(Jan,0)+isnull(Feb,0),....
FROM
(SELECT
YEAR (DateOfTransaction) AS year,
LEFT(DATENAME(MONTH, DateOfTransaction), 3) AS month,
SUM(CASE WHEN TransTypeName LIKE 'credit%' THEN amount ELSE 0 END) -
SUM(CASE WHEN TransTypeName LIKE 'Debit%' THEN amount ELSE 0 END) AS Balance
FROM
.............) AS t
PIVOT (SUM(balance) FOR month IN (jan, feb, march, ...., Dec)) AS pvt)t
Or you can simply add a temp table which stores numbers from 1 to 12
inner join #temp on n>=datepart(mm,DateofTransaction) group by year(transaction), n

Different table layouts

I have a table that looks like this:
|| id | year | userCode | jan | feb | ... ... ... | dec ||
The columns jan - dec holds value (money) data in it. I want it to look like this:
||id | year | month | userCode | value ||
Here's the thing: I can have two values for the same userCode in the same month (and I need them both), so I can't just use SUM. Any ideas?
Thanks in advance!
In SQL Server 2005+ you can easily do this using the UNPIVOT function which transforms data from columns into rows.
The code would be similar to this:
select id, year, month, usercode, value
from yourtable
unpivot
(
value
for month in (Jan, Feb, Mar, Apr, May,
Jun, Jul, Aug, Sep, Oct,
Nov, Dec)
) unpiv
Once the data in the rows, then you can perform any type of aggregation needed.
You can do it with two tables...
One table with Years and Months in it
YearMonths
|| Id | Year | Month | UserCode ||
YearMonthsValues
|| Id | YearMonthId | Value ||
You can do this with union all:
select year, month, userCode, jan, 'jan' as which as value from t union all
select year, month, userCode, feb, 'feb' as which as value from t union all
. . .
select year, month, userCode, dec, 'dec' as which as value from t
I added an extra column which so you would know where the data came from.