Different table layouts - sql

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.

Related

SQLITE combine select result set

I have a table like this:
|-----------------------------|
|someText | Date | someInteger|
|-----------------------------|
What i want is to select a query like this:
|-----------------------------------|
|someText | Jan | Feb | March | ... |
|-----------------------------------|
Basicaly i want to summ all the someInteger grouped by someText for each single month, aka
Select Sum(someInteger) From TABLE
Where Date = [month]
GroupBy someText
...and then, if possible, i would like to combine all the 12 queries of this into one resulting table for ease of use and possibly some optimisation.
With conditional aggregation (assuming that all the dates are in the same year):
select
someText,
sum(case when strftime('%m', date) = '01' then someInteger end) Jan,
sum(case when strftime('%m', date) = '02' then someInteger end) Feb,
sum(case when strftime('%m', date) = '03' then someInteger end) Mar,
...................................................................
from tablename
group by someText
See the demo.
How about group by?
Select strftime('%y-%m', date) as yyyymm,
sum(someInteger)
from t
group by strftime('%y-%m', date);

Summing together values from the same table in different databases

I have a table on each database for a region of a company with the number of sales per month like so:
Region1.dbo.SalesPerMonth Region2.dbo.SalesPerMonth
ID Month Sales ID Month Sales
1 Jan 23 1 Jan 21
2 Feb 19 2 Feb 15
3 Jan 31 3 Jan 25
... ... ... ... ... ...
I am looking to write a query to join these tables into one table that shows the sales for the entire company per month, so it has the total sales from all regions added together:
AllRegions
ID Month Sales
1 Jan 44
2 Feb 34
3 Jan 56
... ... ...
I am however new to SQL and am not sure how to go about doing so. Any help or advice on how to write the query would be greatly appreciated.
Union together the two tables, and then aggregate by ID and Month to generate the sum of sales.
SELECT
ID, Month, SUM(Sales) AS Sales
FROM
(
SELECT ID, Month, Sales
FROM Region1.dbo.SalesPerMonth
UNION ALL
SELECT ID, Month, Sales
FROM Region2.dbo.SalesPerMonth
) t
GROUP BY
ID, Month
ORDER BY
ID;
Demo here:
Rextester
Try this:
WITH DataSource AS
(
SELECT *
FROM Region1.dbo.SalesPerMonth
UNION ALL
SELECT *
FROM Region2.dbo.SalesPerMonth
)
SELECT [id]
,[Month]
,SUM(Sales) AS Sales
FROM DataSource
GROUP BY [id]
,[Month]

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

PostgreSQL group by and order by

I have a table with a date column. I wanted to get the count of months and display them in the order of months. Months should be displayed as 'Jan', 'Feb' etc. If I use to_char function, the order by happens on text. I can use extract(month from dt), but that will also display month in number format. This is part of a report and month should be displayed in 'Mon' format only.
SELECT to_char(dt,'Mon'), COUNT(*) FROM tb GROUP BY to_char(dt,'Mon') ORDER BY to_char(dt,'Mon');
to_char | count
---------+-------
Dec | 1
Jan | 1
Jul | 2
select month, total
from (
select
extract(month from dt) as month_number,
to_char(dt,'mon') as month,
count(*) as total
from tb
group by 1, 2
) s
order by month_number

Combining two T-SQL pivot queries in one

Suppose you had this table:
CREATE TABLE Records
(
RecordId int IDENTITY(1,1) NOT NULL,
CreateDate datetime NOT NULL,
IsSpecial bit NOT NULL
CONSTRAINT PK_Records PRIMARY KEY(RecordId)
)
Now a report needs to be created where the total records and the total special records are broken down by month. I can use these two queries separately:
-- TOTAL RECORDS PER MONTH
SELECT January, February, March, April, May, June,
July, August, September, October, November, December
FROM (
SELECT RecordId, DATENAME(MONTH, CreateDate) AS RecordMonth
FROM dbo.Records
) AS SourceTable
PIVOT (
COUNT(RecordId) FOR RecordMonth IN (January, February, March, April, May, June,
July, August, September, October, November, December)
) AS PivotTable;
-- TOTAL SPECIAL RECORDS PER MONTH
SELECT January, February, March, April, May, June,
July, August, September, October, November, December
FROM (
SELECT RecordId, DATENAME(MONTH, CreateDate) AS RecordMonth
FROM dbo.Records
WHERE IsSpecial = 1
) AS SourceTable
PIVOT (
COUNT(RecordId) FOR RecordMonth IN (January, February, March, April, May, June,
July, August, September, October, November, December)
) AS PivotTable;
The results might look like this:
Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec
total 0 0 2 2 1 0 0 1 2 1 2 4
total special 0 0 1 0 1 0 0 0 0 0 0 2
Is it possible to combine these two queries into a single more efficient query?
I would do it like this:
SELECT
CASE SQ.total_type
WHEN 1 THEN 'total special'
WHEN 2 THEN 'total expensive'
ELSE 'total'
END AS total_type,
SUM(CASE WHEN MONTH(R.CreateDate) = 1 THEN 1 ELSE 0 END) AS January,
SUM(CASE WHEN MONTH(R.CreateDate) = 2 THEN 1 ELSE 0 END) AS February,
SUM(CASE WHEN MONTH(R.CreateDate) = 3 THEN 1 ELSE 0 END) AS March,
...
FROM
dbo.Records R
INNER JOIN
(
SELECT 0 AS total_type UNION ALL -- All
SELECT 1 UNION ALL -- IsSpecial
SELECT 2 -- IsExpensive
) AS SQ ON
(R.IsSpecial | (R.IsExpensive * 2)) & SQ.total_type = SQ.total_type
GROUP BY
SQ.total_type
ORDER BY
SQ.total_type DESC
You can only have one aggregate (COUNT(RecordId)) per pivot so all you do is combine into one result set with a UNION ALL with a suitable extra column to identify each pivot.
Otherwise, you have no way to distinguish the 2 different aggregates in the pivot
Thanks for the solution Tom, that answers my pivot question.
Too bad for me I had the wrong question. For my problem I'm now feeling it would be better to use a plain grouping query like this instead:
SELECT DATENAME(MONTH, CreateDate) AS Month,
COUNT(*) AS Total,
SUM(CASE
WHEN IsSpecial = 1 THEN 1
ELSE 0
END) AS TotalSpecial,
SUM(CASE
WHEN IsExpensive = 1 THEN 1
ELSE 0
END) AS TotalExpensive
FROM Records
GROUP BY DATENAME(MONTH, CreateDate);
Then all that is left to do is rotate the results before they are presented. Nice to know eh?