Show Report - Click Here In my query I have a year field, and I have column grouping on it. I have row grouping on Product group, Product section, and item. If there are no sales in a section for this year and sales were $214 last year, my difference column for that section shows $214 not ($214). Mind you, no sales equal no data in the database, so this year sales is a null value in the report.
This is my expression that I am using, however it is not working:
=IIF(
ISNothing(Sum(IIF(Fields!Year.Value = MAX(Fields!Year.Value),
1,
0) * Fields!Subtotal.Value)) = True,
-1 * (Sum(IIF(Fields!Year.Value = Min(Fields!Year.Value),
1,
0) * Fields!Subtotal.Value)),
Sum(IIF(Fields!Year.Value = Max(Fields!Year.Value),
Fields!Subtotal.Value,
-1 * Fields!Subtotal.Value))
)
As you know your problem is generated in this expression:
Sum(IIF(Fields!Year.Value = Max(Fields!Year.Value),
Fields!Subtotal.Value,
-1 * Fields!Subtotal.Value))
You mentioned in comments there is no rows for Stock Cabinets in 2015 so the maximum year value is 2014 for that group.
Try using this:
Sum(IIF(Fields!Year.Value = Today.Year,
Fields!Subtotal.Value,
-1 * Fields!Subtotal.Value))
It will work if your maximum year is the current calendar year. Today.Year takes the current calendar year of the system at runtime.
UPDATE: I tried to create a minimal and verificable example of your problem.
This is the dataset I've used.
select 10 Value, 2015 [Year], 'Otro' Category
union all
select 20 Value, 2015 [Year], 'Otro' Category
union all
select 30 Value, 2015 [Year], 'Otro' Category
union all
select 10 Value, 2014 [Year], 'Otro' Category
union all
select 7 Value, 2014[Year], 'Stock Cabinets' Category
union all
select 3 Value, 2014 [Year], 'Stock Cabinets' Category
I used the same expression in my total column, the today.Year expression is the only change I made.
=IIF(
ISNothing(Sum(IIF(Fields!Year.Value = max(Fields!Year.Value),
1,
0) * Fields!Value.Value)) = True,
-1 * (Sum(IIF(Fields!Year.Value = Min(Fields!Year.Value)
,1
,0) * Fields!Value.Value)),
Sum(IIF(Fields!Year.Value = Today.Year,
Fields!Value.Value,
-1 * Fields!Value.Value))
)
In a matrix I set this data arrangement:
I get this:
Let me know if this can help you.
I figured it out. I used this for my expression:
=IIF(MAX(Fields!Year.Value)<> MAX(Parameters!Year.Value(0)), Sum(IIF(Fields!Year.Value = Max(Fields!Year.Value), Fields!Subtotal.Value, -1*Fields!Subtotal.Value))*-1, Sum(IIF(Fields!Year.Value = Max(Fields!Year.Value), Fields!Subtotal.Value, -1*Fields!Subtotal.Value)))
Related
I want to find the number of days from my SQL table before my instock level goes negative. Is there a way to do that on SQL? I can find the number of days that have negative instock levels but I am not able to figure out a way to stop the counter for days when instock goes negative.
create TEMPORARY VIEW instock_ssd_fc as
( select
ilbo.asin,
ilbo.snapshot_day,
sum(coalesce(ilbo.on_hand_quantity, 0) - coalesce(greatest(ilbo.allocated_quantity, ilbo.bound_quantity), 0)) as inventory_units_ssd_fc,
sum(coalesce(ilbo.in_transit_quantity, 0)) as in_transit_quantity_ssd_fc,
sum(coalesce(ilbo.unallocated_customer_demand,0)) as unallocated_customer_demand_ssd_fc,
sum(case when iog.inventory_owner_group_id is not null then coalesce(ilbo.on_hand_quantity, 0) - coalesce(greatest(ilbo.allocated_quantity, ilbo.bound_quantity), 0) else 0 end) as inventory_units_retail_ssd_fc
from d_unified_inv_level_by_owner as ilbo
inner join asin_selected as a
on a.asin = ilbo.asin
left join iog
on ilbo.inventory_owner_group_id = iog.inventory_owner_group_id
and ilbo.region_id = ${region_id}
where ilbo.region_id = ${region_id}
and upper(ilbo.inventory_condition_code) = 'SELLABLE'
and ilbo.snapshot_day between cast('${date}' as timestamp) - interval 1 weeks and cast('${date}' as timestamp)
and ilbo.warehouse_id = '${fc}'
group by ilbo.asin, ilbo.snapshot_day
);
From the above query, I want to check how many days the ASIN had a positive inventory. For example, if I start looking for instock levels from 12/27 and go behind, if on snapshot_day of 12/06 the inventory level goes to negative for the first time starting from 12/27, my number of days will be 21.
Assuming your table has a column date for the date and instock for the quantity, you could use try:
SELECT COUNT(*)
FROM yourTable
WHERE date < (SELECT date FROM yourTable
WHERE instock < 0
ORDER BY date LIMIT 1);
I'm trying to make a report that will display how many patients came in during a specific time frame for an age range. This is what I got so far, but the numbers its outputting are wrong, so I'm not sure what I missed. I've followed a couple of examples on here, but none have worked so far. Not sure if its cause I'm Joining to a different table or what.
select COUNT (DISTINCT MPFILE.PATIENT_NO) as 'Male 0-4'
from ENHFILE
Join MPFILE
on MPFILE.PATIENT_NO = ENHFILE.PATIENT_NO
where ENHFILE.COSITE = '300'
and ENHFILE.VISIT_PURPOSE = '2'
and MPFILE.SEX = 'M'
and (DATEDIFF(hour,MPFILE.DOB,GETDATE())/8766) > 5
and ENHFILE.ENCOUNTER_DATE between (#StartDate) and (#EndDate)
select COUNT (DISTINCT MPFILE.PATIENT_NO) as 'FeMale 0-4'
from ENHFILE
Join MPFILE
on MPFILE.PATIENT_NO = ENHFILE.PATIENT_NO
where ENHFILE.COSITE = '300'
and ENHFILE.VISIT_PURPOSE = '2'
and MPFILE.SEX = 'F'
and (DATEDIFF(hour,MPFILE.DOB,GETDATE())/8766) > 5
and ENHFILE.ENCOUNTER_DATE between (#StartDate) and (#EndDate)
Here is something that should get you what you want.
--First i just created some test data
if object_id('tempdb..#temp') is not null drop table #temp
select '8/15/1995' as DOB into #temp union all --Note this person is 21
select '8/16/1995' union all --Note this person is 21 TODAY
select '8/17/1995' union all --Note this person is 21 TOMORROW
select '4/11/1996' union all
select '5/15/1997' union all
select '9/7/2001'
--set the years old you want to use here. Create another variable if you need to use ranges
declare #yearsOld int
set #yearsOld = 21
select
convert(date,DOB) as DOB,
--This figures out how old they are by seeing if they have had a birthday
--this year and calculating accordingly. It is what is used in the filter
--I only put it here so you can see the results
CASE
WHEN CONVERT(DATE, CONVERT(VARCHAR(4), YEAR(GetDate()))+ '-'+ CONVERT(VARCHAR(2),MONTH(DOB)) + '-' + CONVERT(VARCHAR(2),DAY(DOB))) <= GETDATE() THEN DATEDIFF(yy,DOB,GETDATE())
ELSE DATEDIFF(yy,DOB,GETDATE()) -1
END AS YearsOld
from #temp
where
--here is your filter. Feel free to change the >= to what ever you want, or combine it to make it a range.
CASE
WHEN CONVERT(DATE, CONVERT(VARCHAR(4), YEAR(GetDate()))+ '-'+ CONVERT(VARCHAR(2),MONTH(DOB)) + '-' + CONVERT(VARCHAR(2),DAY(DOB))) <= GETDATE() THEN DATEDIFF(yy,DOB,GETDATE())
ELSE DATEDIFF(yy,DOB,GETDATE()) -1
END >= #yearsOld
EDIT
This is your method which doesn't account for if they have had a birthday this year. I use some test data. Notice the person born on 8/18/1995. They turn 21 tomorrow but using (DATEDIFF(hour,DOB,GETDATE())/8766) >= #yearsOld includes them when it shouldn't...
--First i just created some test data
if object_id('tempdb..#temp') is not null drop table #temp
select '8/15/1995' as DOB into #temp union all --Note this person is 21
select '8/16/1995' union all --Note this person is 21 TODAY
select '8/18/1995' union all --Note this person is 21 TOMORROW
select '4/11/1996' union all
select '5/15/1997' union all
select '9/7/2001'
--set the years old you want to use here. Create another variable if you need to use ranges
declare #yearsOld int
set #yearsOld = 21
select
convert(date,DOB) as DOB,
--This figures out how old they are by seeing if they have had a birthday
--this year and calculating accordingly. It is what is used in the filter
--I only put it here so you can see the results
CASE
WHEN CONVERT(DATE, CONVERT(VARCHAR(4), YEAR(GetDate()))+ '-'+ CONVERT(VARCHAR(2),MONTH(DOB)) + '-' + CONVERT(VARCHAR(2),DAY(DOB))) <= GETDATE() THEN DATEDIFF(yy,DOB,GETDATE())
ELSE DATEDIFF(yy,DOB,GETDATE()) -1
END AS YearsOld
from #temp
where
--here is your filter. Feel free to change the >= to what ever you want, or combine it to make it a range.
(DATEDIFF(hour,DOB,GETDATE())/8766) >= #yearsOld
RESULTS
DOB | YearsOld
1995-08-15 | 21
1995-08-16 | 21
1995-08-18 | 20 --this shouldn't be here...
I am performing an operation to work out a percentage based on 2 values.
I have a single table that tracks an overall value against months and years.
Table Name - donation_tracker
I am comparing across all months across current and previous year then performing a calculation such as:
Current Value (Month- January, Year- 2014, CityID- 1) / Previous Value (Month- January, Year- 2013, CityID- 1) = Division Value * 100 = New Percentage Value.
Some of the math operations appear to be correct but some are incorrect for example the image below is showing 140 when it should be 130.
The values I am quering are as follows:
The column donation_amount is set as
Type = Decimal
Length = 10,2.
Sum should be 130...
SQL CODE-
SELECT city_markers.City_ID, city_markers.City_Name, city_markers.City_Lng, city_markers.City_Lat, SUM( d2.Donation_Amount ) , d1.Month, d1.Year, round( (
D2.Donation_amount / D1.Donation_amount
) *100, 2 )
FROM `city_markers`
INNER JOIN donation_tracker d1 ON city_markers.City_ID = d1.City_ID
INNER JOIN donation_tracker D2 ON d1.month = D2.month
AND d1.month = 'January'
AND d2.month = 'January'
AND d2.year = '2014'
AND D1.year = D2.year -1
AND D1.Location_ID = D2.Location_ID
GROUP BY city_markers.City_ID
Thank you.
You do not sum up the amounts here:
round( (D2.Donation_amount / D1.Donation_amount) *100, 2 )
So the result is calculated by the values of each first row:
round( (70 / 50) *100, 2 ) ==> 140
Use sum() to get the intended result:
round( (sum(D2.Donation_amount) / sum(D1.Donation_amount)) *100, 2 )
I have a list of ID’s Shown below.
AT0920130004
AT0920130005
AT0920130006
AT0920130007
AT0920130008
AT0920130009
AT0920130010
AT1020130001
AT1020130002
AT1020130003
AT1020130004
AT1020130005
AT1120130003
AT1120130004
AT1120130005
AT1120130006
Here an example record has the format ATmmyyyyxxxx.
where
AT represents location,
mm represents month eg 10 would be October
yyyy represents year eg. 2013
xxxx represents the increasing seed of numbers.
Now I need to select an ID which is generated in the end of the month.
For ex: last id of September i.e. AT0920130010.
Any suggestions are appreciated.
You can use this query to get max ID for each month and year
select substring([id], 3, 6) MonthYear, max([id]) MaxID
from yourtable
group by substring([id], 3, 6)
To get max ID for one specific month, you can use this query:
select max([id])
from yourtable
where cast(substring([id], 5, 4) as int) = 2013 -- year
and cast(substring([id], 3, 2) as int) = 9 -- month
try this :
select MAX(t.ID) from TableName t
group by SUBSTRING(t.ID, 3, 2)
You basically want to get the max id that matches a location, a month and a year. Something like this should do it:
SELECT max(id)
FROM myTable
WHERE substring(id, 0, 2) = [location]
AND susbstring(id, 2, 2) = [month]
AND substring(id, 4, 4) = [year]
try this(this will return whole field, and just id):
SELECT YOUR_FIELD, MAX(RIGHT(YOUR_FIELD,4)) AS just_id FROM YOUR_TABLE WHERE RIGHT(YOUR_FIELD,LENGTH(YOUR_FIELD)-2) LIKE '09%'
Here's the report:
This is how I got the percentages for column the '%Change of most recent year".
=((Last(Fields!Quantity.Value,"Child") - First(Fields!Quantity.Value)) / First(Fields!Quantity.Value))`
= ((54675 - 55968)/55968 ) = -2.31%'
= ((54675 - 57849)/57849) = -5.49%'
It will always take the first year '2012' in this case and get the percentages against each other year. If I enter the years 2005,2004,2003,2002,2001 it will always take the first year and do a percentages against each additional year. 2005 to 2004, 2005 to 2003, 2005 to 2002 and so on. I can have as many as 2 column (year) to many columns.
I need to do it for the Total and Subtotal but it won't work because it's in a different scope.
data is = row Child group
Sub Total: = row Parent group
Total: = row Total group
Year = Column Period group
Query use to get result.
SELECT MEMBERSHIP_CODE
, PERIOD, COUNT(DISTINCT ID) AS Distinct_ID
, SUM(QUANTITY) AS Quantity
, '01-Personal' AS Child
, '01-Overall' AS Parent
, 'Total' as Total
FROM vf_Sshot AS vfs
INNER JOIN vProd AS vP ON vfs.PRODUCT_CODE = vP.PRODUCT_CODE
INNER JOIN vMem_Type vMT on vMT.Member_Type = vfs.Member_Type
WHERE (PERIOD IN ( (SELECT Val from dbo.fn_String_To_Table(#Periods,',',1))))
AND (vMT.MEMBER_TYPE NOT IN ('a','b','c'))
AND (vfs.STATUS IN ( 'A', 'D', 'C'))
AND (MEMBERSHIP_CODE NOT IN ('ABC', 'DEF' ))
and vP.PROD_TYPE in ('DUE','MC','SC')
and vMT.Member_Record = '1'
GROUP BY MEMBERSHIP_CODE, PERIOD
Any ideas?
How would I produce this output?
TOTAL: 57,573 58,941 57,573 61,188 57,573 61,175 57,175
This is the easiest way of solving your problem. In your query, identify the sum for the latest period on a separate column (you can transform your query into a CTE, so that you don't have to change your base query a lot):
WITH query AS (
SELECT MEMBERSHIP_CODE
, PERIOD, COUNT(DISTINCT ID) AS Distinct_ID
, SUM(QUANTITY) AS Quantity
, '01-Personal' AS Child
, '01-Overall' AS Parent
, 'Total' as Total
...
UNION
SELECT
...
)
SELECT
A.MEMBERSHIP_CODE,
A.PERIOD,
A.Distinct_ID,
A.Child,
A.Parent,
A.Total,
A.Quantity,
B.Quantity AS LastPeriodQuantity
FROM
query A INNER JOIN
(SELECT *, ROW_NUMBER() OVER(PARTITION BY MEMBERSHIP_CODE, Distinct_ID, Child, Parent ORDER BY PERIOD DESC) as periodOrder FROM query) B ON
A.MEMBERSHIP_CODE = B.MEMBERSHIP_CODE AND
A.DISTINCT_ID = B.DISTINCT_ID AND
A.Parent = B.Parent AND
A.Child = B.Child AND
A.Total = B.Total AND
B.PeriodOrder = 1
And then on all your totals/subtotals/columns you will be accessing a column that is being grouped/filtered by the same rules than your denominator. Your expression can remain, for all cells, something like this:
=(Fields!LastPeriodQuantity.Value - Fields!Quantity.Value) / Fields!Quantity.Value