I have data in following format
Client Business Unit Year Quarter USD Amt
BalckRock Pricing 2010 Q1 234
BalckRock Pricing 2010 Q2 343
BalckRock Pricing 2010 Q3 545
BalckRock Pricing 2010 Q4 5435
BalckRock Pricing 2011 Q1 5425
BalckRock Pricing 2011 Q2 3524
BalckRock Pricing 2011 Q3 54
BalckRock Pricing 2011 Q4 5425
BalckRock Pricing 2012 Q1 545
BalckRock Pricing 2012 Q2 5445
BalckRock Pricing 2012 Q3 545
BalckRock Pricing 2012 Q4 4545
BalckRock Sales 2010 Q1 23
BalckRock Sales 2010 Q2 3434
BalckRock Sales 2010 Q3 4234
BalckRock Sales 2010 Q4 4234
BalckRock Sales 2011 Q1 3423
BalckRock Sales 2011 Q2 1
BalckRock Sales 2011 Q3 1341
BalckRock Sales 2011 Q4 434
BalckRock Sales 2012 Q1 421
BalckRock Sales 2012 Q2 42
BalckRock Sales 2012 Q3 434
BalckRock Sales 2012 Q4 4214
And I want it in following format
Client Business Unit 2010 2011 2012
BalckRock Pricing 6557 14428 11080
BalckRock Sales 11925 5199 5111
Basically the sum of USD amnt year wise, but years as the column heading
Can anyone help me in this ?
There are different ways, you can use PIVOT (static or dynamic depending on your needs) or you can simply use a CASE:
SELECT Client,
[Business Unit],
SUM(CASE WHEN [Year] = 2010 THEN [USD Amt] ELSE 0 END) [2010],
SUM(CASE WHEN [Year] = 2011 THEN [USD Amt] ELSE 0 END) [2011],
SUM(CASE WHEN [Year] = 2012 THEN [USD Amt] ELSE 0 END) [2012]
FROM YourTable
GROUP BY Client, [Business Unit]
Using PIVOT:
SELECT *
FROM ( SELECT Client, [Business Unit], [USD Amt], [Year]
FROM YourTable) T
PIVOT (SUM([USD Amt]) FOR [Year] IN ([2010],[2011],[2012])) PT
You can easily use a PIVOT for this. As the other have said you can use a Static Pivot that you code the columns that you want or you can use a Dynamic Pivot, which get the list of columns at run-time.
Static Pivot (See Sql Fiddle for Demo)
select *
from
(
select client, businessunit, year, USD_Amount
from t
) x
pivot
(
sum(USD_Amount)
for year in ([2010], [2011], [2012])
) p
But for this, I might recommend a dynamic Pivot so you don't have to change you code when you get into a new year. (See Sql Fiddle with Demo)
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(year)
from t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT client, businessunit, ' + #cols + ' from
(
select client, businessunit, year, USD_Amount
from t
) x
pivot
(
sum(USD_Amount)
for year in (' + #cols + ')
) p '
execute(#query)
Both queries will produce the same results. However, the plus with the dynamic pivot is that when you have data from additional years, you will not have to update the query to include those fields. The first part of the query gets the list of the distinct years in your table, it then uses that list of years to determine the SUM that you are looking for.
-- Pivot table with one row and five columns
SELECT Client Business Unit Year Quarter USD Amt,[2010],[2011],[2012]
FROM
(SELECTClient Business Unit Year Quarter USD Amt
FROM Table) AS SourceTable
PIVOT
(
sum(USD Amt)
FOR Year IN ([2010], [2011], [2012])
) AS PivotTable;
Related
My fiscal year begins on April 1 and I need to include 1 full year of historical data plus current fiscal year as of today. In DAX this looks like:
DATESBETWEEN(Calendar_Date
,IF(MONTH(TODAY()) < 4
,DATE(YEAR(TODAY())-2, 4, 1)
,DATE(YEAR(TODAY())-1, 4, 1)
)
,DATE(TODAY())
)
I need to create this same range as a filter in a T-SQL query, preferably in the "WHERE" clause, but I am totally new to sql and have been unsuccessful in finding a solution online. Any help from more experienced people would be much appreciated!
If you just want to find these values and use as a where filter this is fairly straightforward date arithmetic, the logic for which you already have in your DAX code:
declare #dates table(d date);
insert into #dates values
('20190101')
,('20190601')
,('20200213')
,('20201011')
,('20190101')
,(getdate())
;
select d
,dateadd(month,3,dateadd(year,datediff(year,0,dateadd(month,-4,d))-1,0)) as TraditionalMethod
,case when month(d) < 4
then datetime2fromparts(year(d)-2,4,1,0,0,0,0,0)
else datetime2fromparts(year(d)-1,4,1,0,0,0,0,0)
end as YourDAXTranslated
from #dates;
Which outputs:
d
TraditionalMethod
YourDAXTranslated
2019-01-01
2017-04-01 00:00:00.000
2017-04-01 00:00:00
2019-06-01
2018-04-01 00:00:00.000
2018-04-01 00:00:00
2020-02-13
2018-04-01 00:00:00.000
2018-04-01 00:00:00
2020-10-11
2019-04-01 00:00:00.000
2019-04-01 00:00:00
2019-01-01
2017-04-01 00:00:00.000
2017-04-01 00:00:00
2021-07-22
2020-04-01 00:00:00.000
2020-04-01 00:00:00
However, I would suggest that you may be better served by creating a Dates Table to which you apply filters and from which you join to your transactional data to return the values you require. In an appropriately configured environment this will make full use of available indexes and should provide very good performance.
A very basic tally table approach to generate such a Dates Table is as follows, which returns all dates and their fiscal year start dates for 2015-01-01 to 2042-05-18:
with t as (select t from(values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) as t(t))
,d as (select dateadd(day,row_number() over (order by (select null))-1,'20150101') as d from t,t t2,t t3,t t4)
select d as DateValue
,case when month(d) < 4
then datetime2fromparts(year(d)-1,4,1,0,0,0,0,0)
else datetime2fromparts(year(d),4,1,0,0,0,0,0)
end as FinancialYearStart
from d
order by DateValue;
How to select only max values in a group in the following set
id productid price year
---------------------------
1 11 0,10 2015
2 11 0,12 2016
3 11 0,11 2017
4 22 0,08 2016
5 33 0,02 2016
6 33 0,01 2017
Expected result for each productid and max year would be
id productid price year
---------------------------
3 11 0,11 2017
4 22 0,08 2016
6 33 0,01 2017
This works for me.
ExecuteSQL (
"SELECT t.id, t.productid, t.price, t.\"year\"
FROM test t
WHERE \"year\" =
(SELECT MAX(\"year\") FROM test tt WHERE t.productid = tt.productid)"
; " " ; "")
Adapted from this answer:
https://stackoverflow.com/a/21310671/832407
A simple SQL query will give you a last year for every product record
ExecuteSQL (
"SELECT productid, MAX ( \"year\")
FROM myTable
GROUP By productid";
"";"" )
To get to the price for that year is going to be trickier, as FileMaker SQL does not fully support subqueries or temp tables.
I'm trying to pivot a table in Postgres. My table 'sample' has many columns (code, sector, item, year, period, value, preorder), instead of having 1 concept, 1 year, 1 value per row, i want the concept with values by year. From this;
Item Value Year PreOrder
Sales 50 2011 1
Costs -20 2011 2
GrossProfit 30 2011 3
Expenses -5 2011 4
Tax -3 2011 5
Profit 22 2011 6
Sales 45 2012 3
Costs -20 2012 4
GrossProfit 25 2012 5
Expenses -5 2012 6
Tax -3 2012 7
Profit 17 2012 8
To this:
Item 2011 2012
Sales 50 45
Costs -20 -20
GrossProfit 30 25
Expenses -5 -5
Tax -3 -3
Profit 22 17
Using crosstab in Postgres:
Select * from crosstab($$Select item, year, value from sec_sample
Where cik=320193
AND period='Annual'
AND Sector='Agro'
Order by year, preorder
$$,
$$VALUES ('2011'::int), ('2012')$$)
AS value("item" varchar(255), "2011" numeric(20,2), "2012" numeric(20,2));
However this results in:
Item 2011 2012
Sales 50
Costs -20
GrossProfit 30
Expenses -5
Tax -3
Profit 22
Sales 45
Costs -20
GrossProfit 25
Expenses -5
Tax -3
Profit 17
Any idea how i can modify my query? Thx
AFAIK, to group by item you have to order by item:
Select * from crosstab($$Select item, year, value from sec_sample
Where cik=320193
AND period='Annual'
AND Sector='Agro'
Order by item, year, preorder
$$,
$$VALUES ('2011'::int), ('2012')$$)
AS value("item" varchar(255), "2011" numeric(20,2), "2012" numeric(20,2));
But you can pivot without using crosstab, like this:
select
s.item,
sum(case when s.year = 2011 then s.value else 0 end) as "2011",
sum(case when s.year = 2012 then s.value else 0 end) as "2012"
from sec_sample as s
group by s.item
order by min(s.preorder)
I think it's easier to modify this type of query
sql fiddle demo
I have a list of purchases by date. EG:
ItemCode, Purchase Date, Purchase Qty
XXX, 01 Jan 2012, 10
XXX, 10 Jan 2012, 5
For the item I have a corresponding Sales transactions:
Item, Sales Date, Sales Qty
XXX, 02 Jan 2012, -5
XXX, 09 Jan 2012, -3
XXX, 11 JAN 2012, -3
I am looking to get a SQL query (Without a cursor), to get the balance on each purchase order quantity. I.e Run each purchase (First in first out) to 0. (For the purposes of aging inventory )
How can you join the Purchases to the Sales to get this balance remaining each purchased Inventory Lot? Is this possible without a cursor?
Yes.
You union the two tables together, and run a running total on the resulting set.
;with cte as
(
select itemcode, purchasedate as tdate, purchaseqty as qty from purchases
union
select itemcode, salesdate, salesqty from sales
)
select
t1.*,
SUM(t2.qty)
from cte t1
left join cte t2
on t1.tdate>=t2.tdate
and t1.item = t2.item
group by t1.item, t1.pdate, t1.qty
To get the stock remaining at any particular time the same principal applies.
select p1.*,
case when (select SUM(abs(qty)) from sales) > SUM(p2.qty) then 0
else SUM(p2.qty) - (select SUM(abs(qty)) from sales) end as stockremaining
from purchases p1
left join purchases p2 on p1.item = p2.item
and p2.purchasedate <= p1.purchasedate
group by p1.purchasedate, p1.item, p1.qty
gives
1 2012-01-01 10 0
1 2012-01-10 5 4
I'm trying to create a formula in Crystal Reports using the below data that will calculate the difference of DxLoaded in the current RunDt minus the previous month RunDt for each of the two Data Sources. Each month a new RunDt will be populated. When the report is refreshed I need to have the formula calculate using the most current RunDt comparing it to the previous RunDt for each Data Source.
For example, I would like to calculate 5,491,932 for the 1203 RunDt minus 3,830,842 for the 1202 RunDt. Then have the formula do that for each Data Source that might be populated. There will also be service year of 2012 for the same Data Source and would like 2011 compared only with 2011 and 2012 with 2012. I've tried using the previous function but haven't had luck with obtaining the correct results.
Yr Data_Source RunDt_YYMM DxLoaded
2011 ABS 1203 5,491,932
2011 ABS 1202 3,830,842
2011 IALT 1203 9,193,144
2011 IALT 1202 6,578,678
2012 ABS 1203 1,837,900
2012 ABS 1202 1,083,124
2012 IALT 1203 4,223,111
2012 IALT 1202 2,985,543
Any help of suggestions are greatly appreciated!!
Thank you!
Assuming that you want the output to appear in the order given in the question, and that you want the difference to appear next to the most recent RunDt_YYMM value for the data source and year:
Explicitly sort the dataset in the order required - ie. Yr ascending, Data_Source ascending, RunDt_YYMM descending. (It should be possible to do this either in the query or in the Crystal Record Sort expert.)
Enter a formula like the following (amend to match your table name):
if NextIsNull ({SummaryTable.Yr}) then 0 else
if {SummaryTable.Data_Source}=Next({SummaryTable.Data_Source}) and
{SummaryTable.Yr}=Next({SummaryTable.Yr})
then {SummaryTable.DxLoaded} - Next({SummaryTable.DxLoaded})
Drag and drop the new formula from the Field Explorer into the report detail section, next to the DxLoaded field.
It's very easy to get bogged down with this sort of problem. The trick is to sort the data out in the query by joining the table to itself using the rundt column. You can either do this in crystal using a custom command or what I prefer to do is create a view or stored procedure in SQL. For example:
SELECT *
INTO #TEMP
FROM (
SELECT 2011 Yr, 'ABS' Data_Source, '1203' RunDt_YYMM, 5491932 DxLoaded
UNION SELECT 2011 Yr, 'ABS' Data_Source, '1202' RunDt_YYMM, 3830842 DxLoaded
UNION SELECT 2011 Yr, 'IALT' Data_Source, '1203' RunDt_YYMM, 9193144 DxLoaded
UNION SELECT 2011 Yr, 'IALT' Data_Source, '1202' RunDt_YYMM, 6578678 DxLoaded
UNION SELECT 2012 Yr, 'ABS' Data_Source, '1203' RunDt_YYMM, 1837900 DxLoaded
UNION SELECT 2012 Yr, 'ABS' Data_Source, '1202' RunDt_YYMM, 1083124 DxLoaded
UNION SELECT 2012 Yr, 'IALT' Data_Source, '1203' RunDt_YYMM, 4223111 DxLoaded
UNION SELECT 2012 Yr, 'IALT' Data_Source, '1202' RunDt_YYMM, 2985543 DxLoaded
) A
SELECT * FROM #TEMP
SELECT
a.Yr, a.Data_Source, a.RunDT_YYMM, a.DxLoaded, b.DxLoaded PrevDxLoaded
FROM
#TEMP a
LEFT OUTER JOIN
#TEMP b
ON
b.Yr = a.Yr
AND
b.Data_Source = a.Data_Source
AND
b.RunDT_YYMM = CASE WHEN RIGHT(a.RunDT_YYMM,2) = '01' THEN
CAST(CAST(a.RunDT_YYMM as INT) - 89 AS VARCHAR(4))
ELSE
CAST(CAST(a.RunDT_YYMM as INT) - 1 AS VARCHAR(4))
END
Result:
Yr Data_Source RunDT_YYMM DxLoaded PrevDxLoaded
2011 ABS 1202 3830842 NULL
2011 ABS 1203 5491932 3830842
2011 IALT 1202 6578678 NULL
2011 IALT 1203 9193144 6578678
2012 ABS 1202 1083124 NULL
2012 ABS 1203 1837900 1083124
2012 IALT 1202 2985543 NULL
2012 IALT 1203 4223111 2985543