Transpose data with MS Access SQL - sql

I have a dataset returned from a MS Access SQL query that looks like Table 1.
Table 1
Year Quarter P1 P2
2013 Q1 1 6
2013 Q2 2 9
2013 Q3 5 1
2013 Q4 6 4
2014 Q1 4 3
2014 Q2 8 2
2014 Q3 6 5
2014 Q4 2 4
2015 Q1 2 3
2015 Q2 1 1
I would like to transpose the data to look like Table 2.
Table 2
Year Quarter Value P1
2014 Q3 P1 6
2014 Q3 P2 5
2014 Q4 P1 2
2014 Q4 P2 4
2015 Q1 P1 2
2015 Q1 P2 3
2015 Q2 P1 1
2015 Q2 P2 1
I've been looking around internet and understand that I need to use TRANSPOSE in the query but I can't figure out how to use it especially since I don't want to transpose the two first columns.

I think you can do what you want with union all:
select year, quarter, 'P1' as value, p1
from table1
union all
select year, quarter, 'P2' as value, p2
from table1;
You might want to add where clauses to get only the rows in your desired results.

Related

SQL Query Return 0 on weeks in between

i have this query that works , but the result is not like i want
returns only year and weeks that has data , i want to return 0 to the result
for example this returns
year week totalstop
2017 50 7
2018 1 3
2018 3 5
but i want to return
year week totalstop
2017 50 7
2017 51 0
2017 52 0
2018 1 3
2018 2 0
2018 3 5
and so on
here is the current query
SELECT year(Stopdate)[year],datepart(week,date1) [week],sum(stop) totalstop
from Table1 where
building in (select item from dbo.fn_Split('A1,A2,A3,A4,A5',','))
and
date1 between '2017-12-12' and '2018-05-08'
and grp = 1
group by year(date1),datepart(week,date1)
order by year(date1),[week]
iam using ms sql-server 2016
need help to modify it to my needs as iam out of ideas atm.

oracle SQL convert some columns to rows [duplicate]

This question already has an answer here:
Oracle 11g - Unpivot
(1 answer)
Closed 5 years ago.
I have a table like below and i am trying to find the best query to convert only the months to rows.
**CODE YEAR JAN FEB MAR**
aa 2017 1 2 3
bb 2017 4 5 6
cc 2017 7 8 9
So that the result is:
**CODE YEAR MONTH value**
aa 2017 JAN 1
aa 2017 FEB 2
aa 2017 MAR 3
bb 2017 JAN 4
bb 2017 FEB 5
bb 2017 MAR 6
cc 2017 JAN 7
cc 2017 FEB 8
cc 2017 MAR 9
Could you please help
Setup table with data:
Select * into #tmpTbl from (
Select 'aa' as Code,2017 as Yr, 1 as Jan,2 as Feb,3 as Mar UNION ALL
Select 'bb' as Code,2017 as Yr, 4 as Jan,5 as Feb,6 as Mar UNION ALL
Select 'cc' as Code,2017 as Yr, 7 as Jan,8 as Feb,9 as Mar) z
Transform query to produce flattened results:
SELECT Code, Yr, CrossApplied.Fld, CrossApplied.Val as Value
FROM #tmpTbl
CROSS APPLY (VALUES (JAN,'JAN'),
(FEB,'FEB'),
(MAR,'MAR'))
CrossApplied (Val,Fld)
The structure of your data might be better reworked to make the data more inline with how you want it represented. This works but its a lot of work around to get there from here.

Aggregate values with multiple conditions

I've searched the forum but can't quite find what I'm looking for. Apologies if this has already been answered.
I have a table with the following example values:
FY Period Version Value
2013 3 1 9954
2013 3 2 9954
2013 4 1 11498
2013 4 2 11498
2013 4 3 11498
2014 1 1 448
2014 1 2 448
2014 1 3 0
2014 2 1 3150
2014 2 2 3150
2014 3 1 0
2014 3 2 0
2014 3 3 5059
2014 4 1 11118
2014 4 2 0
2014 4 3 11118
I'm looking to sum the values for the highest version number, within each period and each FY, so the expected result for this particular data set would be:
(9954 + 11498 + 0 + 3150 + 5059 + 11118) = 40,779
I've done something similar previously with the over partition approach but i can't get it to work on this data set. Any pointers would be greatly appreciated.
A simple approach is to use row_number():
select sum(value)
from (select t.*,
row_number() over (partition by fy, period order by version desc) as seqnum
from table t
) t
where seqnum = 1;

Oracle SQL Developer - Trying to return products by quarter

I am trying to return a list of products that only appear in one quarter. I have decided the best way to do this is to I have been fiddling around with my code for a while and tried a COUNT but realised that this wouldn't work as it is counting the number of entries a product has rather than the number of quarters it appears in.
These are my three tables:
SALES FACT TABLE
TIME_KEY PRODUCT_KEY BRANCH_KEY LOCATION_KEY POUNDS_SOLD AVG_SALES UNITS_SOLD
----------------------------- ----------- ---------- ------------ ----------- ---------- ----------
22-DEC-13 08.31.18.442000000 2 B1 L19 21542.39 10821.2 100
21-DEC-10 21.19.37.182000000 3 B8 L5 65487 32793.5 100
13-SEP-13 06.36.03.720000000 7 B2 L15 78541.84 39470.92 400
24-JUN-13 12.21.45.186000000 1 B7 L13 94115 47167.5 220
18-SEP-07 12.58.06.873000000 8 B2 L2 54000 27250 500
11-FEB-11 18.06.08.475000000 8 B9 L6 11123 5636.5 150
28-SEP-13 15.06.20.153000000 6 B3 L16 45896.31 23008.16 120
22-DEC-08 19.34.48.490000000 5 B6 L3 87451.01 43875.51 300
23-JUL-13 20.08.51.173000000 6 B6 L14 69542 34971 400
20-DEC-13 22.47.24.962000000 9 B4 L17 21584.39 10872.2 160
21-DEC-06 19.11.50.472000000 5 B10 L1 10000 27250 500
13-MAR-13 14.13.58.555000000 1 B2 L11 62413 31256 99
06-MAR-13 18.15.40.365000000 4 B6 L10 94785 47542.5 300
20-DEC-13 23.35.12.683000000 2 B5 L18 52359.19 26289.6 220
15-MAR-13 19.11.58.459000000 4 B9 L12 66499.84 33299.92 100
19-DEC-11 13.17.34.443000000 9 B2 L7 51449 26049.5 650
14-FEB-12 10.20.20.787000000 10 B5 L8 66589 33394.5 200
19-DEC-09 10.09.41.844000000 3 B7 L4 99125 49687.5 250
22-MAR-12 19.36.24.790000000 10 B2 L9 62331.66 31765.83 1200
11-JAN-14 19.18.58.595000000 7 B8 L20 35214.85 17667.43 120
TIME DIMENSION TABLE
TIME_KEY DAY DAY_OF_WEEK MONTH QUARTER YEAR
----------------------------- ---------- ----------- --------- ------- ----------
13-MAR-13 14.13.58.555000000 13 WEDNESDAY MARCH Q1 2013
22-DEC-13 08.31.18.442000000 22 SUNDAY DECEMBER Q4 2013
21-DEC-10 21.19.37.182000000 21 TUESDAY DECEMBER Q4 2010
15-MAR-13 19.11.58.459000000 15 FRIDAY MARCH Q1 2013
21-DEC-06 19.11.50.472000000 21 THURSDAY DECEMBER Q4 2006
28-SEP-13 15.06.20.153000000 28 SATURDAY SEPTEMBER Q3 2013
11-JAN-14 19.18.58.595000000 11 SATURDAY JANUARY Q1 2014
11-FEB-11 18.06.08.475000000 11 FRIDAY FEBRUARY Q1 2011
20-DEC-13 22.47.24.962000000 20 FRIDAY DECEMBER Q4 2013
14-FEB-12 10.20.20.787000000 14 TUESDAY FEBRUARY Q1 2012
24-JUN-13 12.21.45.186000000 24 MONDAY JUNE Q2 2013
20-DEC-13 23.35.12.683000000 20 FRIDAY DECEMBER Q4 2013
19-DEC-09 10.09.41.844000000 19 SATURDAY DECEMBER Q4 2009
06-MAR-13 18.15.40.365000000 6 WEDNESDAY MARCH Q1 2013
22-DEC-08 19.34.48.490000000 22 MONDAY DECEMBER Q4 2008
23-JUL-13 20.08.51.173000000 23 TUESDAY JULY Q3 2013
13-SEP-13 06.36.03.720000000 13 FRIDAY SEPTEMBER Q3 2013
18-SEP-07 12.58.06.873000000 18 TUESDAY SEPTEMBER Q3 2007
19-DEC-11 13.17.34.443000000 19 MONDAY DECEMBER Q4 2011
22-MAR-12 19.36.24.790000000 22 THURSDAY MARCH Q1 2012
PRODUCT DIMENSION TABLE
PRODUCT_KEY PRODUCT_NAME BRAND TYPE SUPPLIER_TYPE
----------- ------------------------- -------------------- ---------- ----------------
1 SVF1521P2EB SONY LAPTOP WHOLESALER
2 15-A003SA COMPAQ LAPTOP WHOLESALER
3 15-N271SA HP LAPTOP RETAIL
4 15-N290SA HP LAPTOP RETAIL
5 E6400 DELL LAPTOP RETAIL
6 SVF1521C2EB SONY LAPTOP WHOLESALER
7 SVF1532K4EB SONY LAPTOP WHOLESALER
8 C50-A-1CK TOSHIBA LAPTOP WHOLESALER
9 NX.MF8EK.001 ACER LAPTOP RETAIL
10 NP915S3G-K01UK SAMSUNG LAPTOP RETAIL
This is the code that I am running:
SELECT DISTINCT product.product_name, product.brand, quarter, SUM (sales.units_sold), COUNT (quarter)
FROM sales
INNER JOIN product
ON product.product_key=sales.product_key
INNER JOIN time
ON sales.time_key=time.time_key
GROUP BY quarter, product.product_name, product.brand
ORDER BY brand;
Below is the result once I run the query with the code that I have so far which is obviously not giving me what I want:
PRODUCT_NAME BRAND QUARTER SUM(SALES.UNITS_SOLD) COUNT(QUARTER)
------------------------- -------------------- ------- --------------------- --------------
NX.MF8EK.001 ACER Q4 810 2
15-A003SA COMPAQ Q4 320 2
E6400 DELL Q4 800 2
15-N271SA HP Q4 350 2
15-N290SA HP Q1 400 2
NP915S3G-K01UK SAMSUNG Q1 1400 2
SVF1521C2EB SONY Q3 520 2
SVF1521P2EB SONY Q1 99 1
SVF1521P2EB SONY Q2 220 1
SVF1532K4EB SONY Q1 120 1
SVF1532K4EB SONY Q3 400 1
C50-A-1CK TOSHIBA Q1 150 1
C50-A-1CK TOSHIBA Q3 500 1
I know its probably simple for you guys but I can sense that I am nearly there, I think I just have something the wrong way round and am not translating my intention into code.
The desired output would display products that have only been sold in one quarter. If they were sold in two quarters they would not be considered seasonal.
In your query count(quarter) is going to be the same as count(*). You need to remove quarter from the group by and do the comparison on the number of quarters in a having clause:
SELECT product.product_name, product.brand, MIN(quarter) as quarter, SUM(sales.units_sold)
FROM sales INNER JOIN
product
ON product.product_key = sales.product_key INNER JOIN
time
ON sales.time_key = time.time_key
GROUP BY product.product_name, product.brand
HAVING min(quarter) = max(quarter)
ORDER BY brand;
You could also use:
HAVING count(distinct quarter) = 1
However, count(distinct) is less efficient than most other aggregation functions.

Normalize a Table That Contains Monthly, Yearly and Quarterly Data

How do I normalize this table:
Frequency (PK) Year (PK) Quarter (PK) Month (PK) Value
Monthly 2013 1 1 1
Quarterly 2013 1 0 2
Yearly 2013 0 0 3
The table is not in 2nd normal form, because when Frequency = Yearly Value depends on a subset of the primary key (Frequency, Year)
I've thougt about adding a surrogate key. Then Quarter and Month columns could be nullable.
Surrogate (PK) Frequency Year Quarter Month Value
1 Monthly 2013 1 1 1
2 Quarterly 2013 1 NULL 2
3 Yearly 2013 NULL NULL 3
But this doesn't solve the problem, because the 2nd normal form definition also applies to candidate keys. Dividing the table into three tables based on Frequency doesn't sound like a good idea, because it will introduce if statemments into my business logic:
if (frequency == Monthly) then select from DataMonthly
I'm going to assume that a couple of year's worth of data might look something like this. Correct me if I'm wrong. (I'm going to ignore the issue of whether using zeroes is a good idea or a bad idea.)
Frequency Year Quarter Month Value
--
Monthly 2012 1 1 1
Monthly 2012 1 2 2
Monthly 2012 1 3 3
Monthly 2012 2 4 4
Monthly 2012 2 5 5
Monthly 2012 2 6 6
Monthly 2012 3 7 7
Monthly 2012 3 8 8
Monthly 2012 3 9 9
Monthly 2012 4 10 10
Monthly 2012 4 11 11
Monthly 2012 4 12 12
Quarterly 2012 1 0 2
Quarterly 2012 2 0 5
Quarterly 2012 3 0 8
Quarterly 2012 4 0 11
Yearly 2012 0 0 3
Monthly 2013 1 1 1
Monthly 2013 1 2 2
Monthly 2013 1 3 3
Monthly 2013 2 4 4
Monthly 2013 2 5 5
Monthly 2013 2 6 6
Monthly 2013 3 7 7
Monthly 2013 3 8 8
Monthly 2013 3 9 9
Monthly 2013 4 10 10
Monthly 2013 4 11 11
Monthly 2013 4 12 12
Quarterly 2013 1 0 2
Quarterly 2013 2 0 5
Quarterly 2013 3 0 8
Quarterly 2013 4 0 11
Yearly 2013 0 0 3
From that data we can deduce two functional dependencies. A functional dependency answers the question, "Given one value for the set of attributes 'X', do we know one and only one value for the set of attributes 'Y'?"
{Year, Quarter, Month}->Frequency
{Year, Quarter, Month}->Value
Given one value for the set of attributes {Year, Quarter, Month}, we know one and only one value for the set of attributes {Frequency}. And given one value for the set of attributes {Year, Quarter, Month}, we know one and only one value for the set of attributes {Value}.
The problem you were running into involved including "Frequency" as part of the primary key. It's really not.
This table could do probably without the [Frequency] and [Quarter] column.
Why do you want to have these in? Is there any added value in having the Quarterly and Yearly values precalculated in this table? Comment: Since it's Value's are not just the sum of it's Month's.
So [Quarter] is mandatory.
This will work too:
Year (PK) Quarter (PK) Month (PK) Value
2013 1 1 1
2013 1 0 2
2013 0 0 3
Yearly results:
SELECT
[Value]
FROM [Table1]
WHERE [Year] = 2013 AND [Quarter] = 0 AND [Month] = 0
Quarterly results:
SELECT
[Value]
FROM [Table1]
WHERE [Year] = 2013 AND [Quarter] = 1 AND [Month] = 0
Monthly results:
SELECT
[Value] AS [Results]
FROM [Table1]
WHERE [Year] = 2013 AND [Quarter] = 1 AND [Month] = 1
Would this work for you?