Here I defined the constants 'sell in' and 'sell out' in both sell in and sell out dataset , so I need to calculate RETAIL_MARGIN and RETAIL_MARGIN_PCT .
the formula I defined in such a way that for 'sell out' it should calculate and for 'sell in' it should represent zero value.
the issue what Iam facing in this is its not taking both the constants its calculating 'sell out' for all that should not happen
it should represent sell in and sell out
I provide sample tables and result output how it should be
SELECT
DATA_SOURCE,
CASE WHEN DATA_DOURCE='SELL OUT'
THEN
ZEROIFNULL(ROUND(SALES_VOLUME*(SO_PRICE*(1-0.18)-SI_PRICE*(1-0.18)),2))
ELSE 0 END AS RETAIL_MARGIN,
CASE WHEN DATA_SOURCE= 'SELL OUT'
THEN
ZEROIFNULL(ROUND(DIVO(SI_PRICE*(1-0.18),SO_PRICE*(1-0.18))*100,2))
ELSE 0 END AS RETAIL_MARGIN_PCT
FROM (
SELECT
SOLD_TO,
EAN,
DATA_SOURCE,
ROUND(DIV0(SUM(SALES_VALUE), SUM(SALES_VOLUME)),2) AS SO_PRICE,
ROUND(DIV0(SUM(SI_SALES_VALUE), SUM(SI_SALES_VOLUME)),2) AS SI_PRICE
FROM (
SELECT
A3SOLD_TO,
A3.EAN,
ROUND(DIV0(COALESCE(A3.SALES_VALUE,0),3),2) AS SO_SALES_VALUE,
ROUND(DIV0(COALESCE(A3.SALES_VOLUME,0),3),2) AS SO_SALES_VOLUME,
ROUND(DIV0(ZEROIFNULL( A4.SI_SALES_VALUE),3),2) AS SI_SALES_VALUE,
ROUND(DIV0(ZEROIFNULL( A4.SI_SALES_VOLUME),3),2) AS SI_SALES_VOLUME
FROM (
SELECT
A1.SOLD_TO,
A2.EAN,
A1.DATA_SOURCE,
ROUND(ZEROIFNULL(SUM(A1.SALES_VALUE)),2) AS SALES_VALUE,
ROUND(ZEROIFNULL(SUM(A1.SALES_VOLUME)),2) AS SALES_VALUE
FROM (
SELECT
SOLD_TO,
PRODUCT_CD,
MAX(CALDAY) AS MAX_DATE,
MAX(CALDAY)-90 AS MIN_DATE,
FROM RGM_SALES_GBL.INT_TXN.SELLOUT
WHERE SALE_ORG = '7140'
AND PRODUCT_CD IS NOT NULL
GROUP BY 1,2
)A5
JOIN (
SELECT
SOLD_TO,
PRODUCT_CD,
CALDAY,
'SELL OUT' AS DATA_SOURCE,
ROUND(COALESCE(SUM(SALESVALUE),0),2) AS SALES_VALUE,
ROUND(COALESCE(SUM(SALESCASE),0),2) AS SALES_VOLUME,
FROM RGM_SALES_GBL.INT_TXN.SELLOUT
WHERE SALE_ORG='7140'
AND PRODUCT_CD IS NOT NULL
GROUP BY 1,2,3,4
)AS A1
ON A5.SOLD_TO = A1.SOLD_TO
AND A1.PRODUCT_CD=A5.PRODUCT_CD
AND A1.CALDAY BETWEEN A5.MIN_DATE AND A5.MAX_DATE
INNER JOIN (
SELECT DISTINCT
EAN,
PRODUCT_CD
FROM RGM_SALES_GBL.INT_MD.DIM_PRODUCT
WHERE SALES ORG='7140'
AND EAN != ' '
AND PRODUCT_CD IS NOT NULL
AND BASE_UOM = 'CS'
) AS A2
ON A1.PRODUCT_CD = A2.PRODUCT_CD
GROUP BY 1,2
) AS A3
LEFT JOIN (
SELECT
SOLD_TO,
EAN,
MAX(CALDAY) AS MAX_DATE,
MAX(CALDAY)-90 AS MIN_DATE,
FROM RGM_SALES_GBL.INT_TXN.SELLIN
WHERE SALES_ORG='7140'
AND COUNTRY_CD= '4025'
AND PRODUCT_CD IS NOT NULL
GROUP BY 1,2
)A6
(
SELECT
SOLD_TO,
EAN,
CALDAY,
'SELL IN' AS DATA_SOURCE,
ROUND(ZEROIFNULL(SUM(NET_INV_VALUE_IN_LC)),2) AS SI_SALES_VALUE,
ROUND(ZEROIFNULL(SUM(SALESCASES)),2) AS SI_SALES_VOLUME
FROM RGM_SALES_GBL.INT_TXN.SELLIN
WHERE SOLD_TO NOT IN (
SELECT DISTINCT
SOLD_TO FROM
FROM RGM_SALES_GBL.INT_TXN.SELLOUT
WHERE SALE_ORG='7140'
AND PRODUCT_CD IS NOT NULL
)
AND SALES_ORG = '7140'
AND COUNTRY_CD = '4025'
GROUP BY 1,2,3,4
)A4
ON A4.SOLD_TO = A6.SOLD_TO
AND A4.EAN = A6.EAN
AND A4.CALDAY BETWEEN A6.MIN_DATE AND A6.MAX_DATE
ON A3.SOLD_TO = A4.SOLD_TO
AND A3.EAN=A4.EAN
)
GROUP BY 1,2
)
CREATE TABLE RGM_SALES_GBL.INT_TXN.SELLOUT
(SOLD_TO INT,
EAN INT ,
PRODUCT_CD INT,
CALDAY DATE
SALESVALUE INT,
SALESCASE INT,
SALE_ORG INT,)
VALUES(123,10001,101,5/1/2021,76,35,'7140),
(123,10002,102,5/20/2021,21,15,'7140),
(124,10003,103,6/15/2021,45,14,'7140),
(123,10004,101,6/02/2021,76,43,'7140)
CREATE TABLE RGM_SALES_GBL.INT_TXN.SELLIN
(SOLD_TO INT,
EAN INT ,
CALDAY DATE
NET_INV_VALUE_IN_LC INT,
SALESCASES INT,
SALES_ORG INT,
COUNTRY_CD INT)
VALUES(201,10001,5/1/2021,15,30,'7140','4025'),
(203,10002,5/20/2021,43,49,'7140','4025'),
(204,10003,6/15/2021,38,15,'7140','4025'),
(205,10005,6/02/2021,61,56,'7140','4025')
CREATE TABLE RGM_SALES_GBL.INT_MD.DIM_PRODUCT
(EAN INT,
PRODUCT_CD INT,
BASE_UOM STRING)
VALUES(10001,1001,'CS'),(10002,103,'CS'),(10004,104,'CS')
DATA_SOURCE
RETAIL_MARGIN
RETAIL_MARGIN_PCT
SELL OUT
76
15
SELL OUT
98
13.5
SELL IN
0
0
SELL IN
0
0
Related
I would like the following wide table to be unpivotted but only where a user has a true value against the field, along with the appropriate date.
Current State:
CUSTOMER_ID
First_Party_Email
Third_Party_Email
First_Party_Email_Date
Third_Party_Email_Date
40011111
1
1
2021-01-22 04:38:00.000
2021-01-17 06:38:00.000
50022222
NULL
1
NULL
2021-01-18 04:38:00.000
80066666
1
NULL
2021-01-24 05:38:00.000
NULL
_______________
_______________________
_______________________
_______________________________
_______________________________
Required State:
Customer_ID
Type
Value
Date
40011111
First_Party_Email
1
22/01/2021 04:38
40011111
Third_Party_Email
1
17/01/2021 06:38
50022222
Third_Party_Email
1
18/01/2021 04:38
80066666
First_Party_Email
1
24/01/2021 05:38
_______________________________________________________________________
Associated query to create table and my attempt that doesn't work:
create table Permissions_Obtained
(Customer_ID bigint
,First_Party_Email bit
,Third_Party_Email bit
,First_Party_Email_Date datetime
,Third_Party_Email_Date datetime
)
insert into Permissions_Obtained
(Customer_ID
,First_Party_Email
,Third_Party_Email
,First_Party_Email_Date
,Third_Party_Email_Date
)
VALUES
(40011111, 1, 1, '2021-01-22 04:38', '2021-01-17 06:38'),
(50022222, NULL, 1, NULL, '2021-01-18 04:38'),
(80066666, 1, NULL, '2021-01-24 05:38', null)
select *
from Permissions_Obtained
select
customer_id, Permission
from Permissions_Obtained
unpivot
(
GivenPermission
for Permission in (
First_Party_Email, Third_Party_Email
)
) unpiv1,
unpivot
(
GivenPermissionDate
for PermissionDate in (
First_Party_Email_Date, Third_Party_Email_Date
)
) unpiv2
where GivenPermission = 1
--drop table Permissions_Obtained
Any help would be massively appreciated. TIA
You cannot have multiple unpivots at the same time. Instead you can use Cross Apply or Inner join or union, union all or kind of joins depending on your requirement. I have added a sample answer for this using join and unpivot.
SELECT
unpvt.Customer_ID
, [Type]
, ISNULL(po.First_Party_Email ,po.Third_Party_Email) AS [Value]
,CASE WHEN unpvt.Type = 'First_Party_Email' THEN po.First_Party_Email_Date
ELSE po.Third_Party_Email_Date
END AS [Date]
FROM
(
SELECT
Customer_ID, First_Party_Email , Third_Party_Email
FROM Permissions_Obtained
) p
UNPIVOT
( [Value] FOR [Type] IN
(First_Party_Email , Third_Party_Email )
)AS unpvt
INNER JOIN Permissions_Obtained [po]
on [po].Customer_ID = unpvt.Customer_ID
When un-pivoting multiple columns, CROSS APPLY (VALUES is often the easiest and most effective solution.
It creates a virtual table per-row of the previous table, and therefore un-pivots it into separate rows.
SELECT
p.Customer_Id,
v.[Type],
v.Value,
v.Date
FROM Permissions_Obtained p
CROSS APPLY (VALUES
('First_Party_Email', p.First_Party_Email, p.First_Party_Email_Date),
('Third_Party_Email', p.Third_Party_Email, p.Third_Party_Email_Date)
) v([Type], Value, Date)
where v.Value IS NOT NULL;
I have two tables, LYEAR and CYEAR:
[SKU],[Title],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12]
Columns [SKU],[Title],[1],[2],[3],[4],[5],[6],[7],[8] are populated with information from the CYEAR table and [SKU],[Title],[9],[10],[11],[12] from the LYEAR table.
How would I merge the two tables, so that there are columns with NULL values are dropped, leaving me with one row per SKU?
I have got this far:
WITH LYEAR_ORG ([SKU],[Title],[QTY],[DATE]) AS
(
SELECT
T1.ItemNumber, T1.ItemTitle, (SUM(T2.nqty)) AS [UNITS],
CONVERT(VARCHAR(2), (MONTH(T3.dProcessedOn)))
FROM
StockItem T1
LEFT OUTER JOIN
OrderItem T2 ON T1.pkstockItemId = T2.fkStockItemID_processed
LEFT JOIN
[Order] T3 ON T3.pkOrderID = T2.fkOrderID
WHERE
(YEAR(T3.dProcessedOn)) = (YEAR(getdate())-1)
AND (MONTH(T3.dProcessedOn)) > (MONTH(getdate())-1)
GROUP BY
T1.ItemNumber, T1.ItemTitle,
CONVERT(VARCHAR(2), (MONTH(T3.dProcessedOn)))
),
CYEAR_ORG ([SKU],[Title],[QTY],[DATE]) AS
(
SELECT T1.ItemNumber, T1.ItemTitle, (SUM(T2.nqty)) AS [UNITS], CONVERT(varchar(2),(MONTH(T3.dProcessedOn)))
FROM StockItem T1
LEFT OUTER JOIN OrderItem T2 ON T1.pkstockItemId = T2.fkStockItemID_processed
LEFT JOIN [Order] T3 ON T3.pkOrderID = T2.fkOrderID
WHERE (YEAR(T3.dProcessedOn)) = (YEAR(getdate())-1)
AND (MONTH(T3.dProcessedOn)) < (MONTH(getdate()))
GROUP BY T1.ItemNumber, T1.ItemTitle, CONVERT(varchar(2),(MONTH(T3.dProcessedOn)))
),
LYEAR ([SKU],[Title],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12]) AS (
SELECT *
FROM LYEAR_ORG
PIVOT ( MAX(QTY) FOR DATE in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) as LYEAR_ORDERS
),
CYEAR ([SKU],[Title],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12]) AS (
SELECT *
FROM CYEAR_ORG
PIVOT ( MAX(QTY) FOR DATE in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) as CYEAR_ORDERS
)
SELECT * FROM LYEAR
UNION ALL
SELECT * FROM CYEAR
I am unable to use INSERT INTO as this is a limitation on the Linnworks platform I am working on, it is SQL Server.
On the assumption that LYEAR columns 1-8 are all NULL, and so are CYEAR 9-12, a JOIN with a ton of COALESCEs, rather than a UNION will get you where you want to be. If, though, there are values for both years in any columns, this will go sideways.
SELECT
l.[SKU]
,l.[Title]
,COALESCE(l.[1], c.[1]) AS [1]
,COALESCE(l.[2], c.[2]) AS [2]
,COALESCE(l.[3], c.[3]) AS [3]
,COALESCE(l.[4], c.[4]) AS [4]
,COALESCE(l.[5], c.[5]) AS [5]
,COALESCE(l.[6], c.[6]) AS [6]
,COALESCE(l.[7], c.[7]) AS [7]
,COALESCE(l.[8], c.[8]) AS [8]
,COALESCE(l.[9], c.[9]) AS [9]
,COALESCE(l.[10], c.[10]) AS [10]
,COALESCE(l.[11], c.[11]) AS [11]
,COALESCE(l.[12], c.[12]) AS [12]
FROM
LYEAR AS l
JOIN
CYEAR AS c
ON
c.SKU = l.SKU
AND c.Title = l.Title;
Here's a solution that will allow for there to be data in both LYEAR and CYEAR, and to switch from one to the other based on the month of the year:
SELECT SKU,
Title,
CASE WHEN DATEPART(MM, GETDATE()) > 1
THEN LYEAR.1
ELSE CYEAR.1
END,
CASE WHEN DATEPART(MM, GETDATE()) > 2
THEN LYEAR.2
ELSE CYEAR.2
END,
CASE WHEN DATEPART(MM, GETDATE()) > 3
THEN LYEAR.3
ELSE CYEAR.3
END,
CASE WHEN DATEPART(MM, GETDATE()) > 4
THEN LYEAR.4
ELSE CYEAR.4
END
--Add rest of CASE statements for remaining months
FROM LYEAR AS L
JOIN CYEAR AS C
ON L.SKU = C.SKU
AND L.Title = C.Title
By executing the below SQL 2012 Query, I got the following output
declare
#ticketstatus nvarchar(20) = 'To Be Allocated'
SELECT m1.ClaimSource, m1.Insurance, n1.[Claim Count], n1.[Claim Value],
ISNULL(m1.[0-30],0) [0-30],
ISNULL(m1.[31-60],0) [31-60],
ISNULL(m1.[61-90],0) [61-90],
ISNULL(m1.[91-120],0) [91-120],
ISNULL(m1.[121-210],0) [121-210],
ISNULL(m1.[210++],0) [210++]
FROM (
SELECT *
FROM (
SELECT ClaimSource, Insurance, CurrentBalance _Count, AgeBucket
FROM ClaimMaster
) m
PIVOT (
COUNT(_Count)
FOR AgeBucket IN ([0-30],[31-60],[61-90],[91-120],[121-210],[210++])
) n
) m1
join
(SELECT Insurance, COUNT(Insurance) [Claim Count], SUM(CurrentBalance) [Claim Value] FROM ClaimMaster
WHERE (TicketStatus = #ticketstatus OR #ticketstatus IS NULL)
GROUP BY Insurance) n1
ON m1.Insurance = n1.Insurance
ORDER BY n1.[Claim Count] DESC
How can I get the correct output for Claim Count, Claim Value on the 4, 5 & 6 rows. Instead of showing full claim count, it should show the respective claim count filter by Claim Source such as Claim Count should be 2 and appropriate Claim Value.
Can anyone help me on this.
Add claimsource and join on that as well?
declare
#ticketstatus nvarchar(20) = 'To Be Allocated'
SELECT m1.ClaimSource, m1.Insurance, n1.[Claim Count], n1.[Claim Value],
ISNULL(m1.[0-30],0) [0-30],
ISNULL(m1.[31-60],0) [31-60],
ISNULL(m1.[61-90],0) [61-90],
ISNULL(m1.[91-120],0) [91-120],
ISNULL(m1.[121-210],0) [121-210],
ISNULL(m1.[210++],0) [210++]
FROM (
SELECT *
FROM (
SELECT ClaimSource, Insurance, CurrentBalance _Count, AgeBucket
FROM ClaimMaster
) m
PIVOT (
COUNT(_Count)
FOR AgeBucket IN ([0-30],[31-60],[61-90],[91-120],[121-210],[210++])
) n
) m1
join
(SELECT ClaimSource, Insurance, COUNT(Insurance) [Claim Count], SUM(CurrentBalance) [Claim Value] FROM ClaimMaster
WHERE (TicketStatus = #ticketstatus OR #ticketstatus IS NULL)
GROUP BY ClaimSource, Insurance) n1
ON m1.Insurance = n1.Insurance and m1.ClaimSource = n1.ClaimSource
ORDER BY n1.[Claim Count] DESC
I'm using MS-SQL 2008 R2.
I have 2 Queries which are returning the required results.
But I need to add the two results from each queries to provide a final value [Enterprise Value]. I'm sure this is very straight forward but I'm going round in circles on this, have tried incorporating SUM which I think is the right approach?
Here is the full query as it currently stands:
declare #d1 datetime='2015-12-22'
(select
c.fs_perm_sec_id,
((c.p_price * s.p_com_shs_out)/1000) as [Enterprise Value]
from fp_v1.fp_basic_bd c
left join edm_v1.edm_security_entity_map e
on e.fs_perm_sec_id= c.fs_perm_sec_id
left join fp_v1.fp_basic_sho s
on s.fs_perm_sec_id = c.fs_perm_sec_id
and c.date=#d1
where s."date" =
(
select MAX(s2."date")
from fp_v1.fp_basic_sho s2
where s2.fs_perm_sec_id=c.fs_perm_sec_id
and s2."date" <= c."date"
)
and c."date"=#d1
and e.termination_date is null
and c.fs_perm_sec_id = 'GPHC8W-S-GB')
UNION ALL
select
ff.fs_perm_sec_id,
((FF_debt + ff_pfd_stk + ff_min_int_accum) - FF.ff_cash_st) as [Enterprise Value]
from ff_v2.ff_basic_af_v2 FF
where FF."date" =
( select MAX(FF2."date")
from ff_v2.ff_basic_af_v2 FF2
where FF2.fs_perm_sec_id=FF.fs_perm_sec_id
and FF.date <= FF2.date
)
and FF.fs_perm_sec_id =('GPHC8W-S-GB')
When inserting a "UNION ALL" between the two queries I get the following results:
fs_perm_sec_id Enterprise Value
GPHC8W-S-GB 9270.5204655
GPHC8W-S-GB 835
What I would like to achieve is a sum of the two values brought onto one row, i.e.:
fs_perm_sec_id Enterprise Value
GPHC8W-S-GB 10105.52
Thanks for your help.
Final SQL:
declare #d1 datetime='2015-12-23'
Select fs_perm_sec_id, SUM([Enterprise Value]) AS 'Enterprise Value'
from
(
(select
c.fs_perm_sec_id,
((c.p_price * s.p_com_shs_out)/1000) as [Enterprise Value]
from fp_v1.fp_basic_bd c
left join edm_v1.edm_security_entity_map e
on e.fs_perm_sec_id= c.fs_perm_sec_id
left join fp_v1.fp_basic_sho s
on s.fs_perm_sec_id = c.fs_perm_sec_id
and c.date=#d1
where s."date" =
(
select MAX(s2."date")
from fp_v1.fp_basic_sho s2
where s2.fs_perm_sec_id=c.fs_perm_sec_id
and s2."date" <= c."date"
)
and c."date"=#d1
and e.termination_date is null
and c.fs_perm_sec_id in ('FT9TC5-S-GB','GPHC8W-S-GB','R85KLC-S-US'))
UNION ALL
select
ff.fs_perm_sec_id,
((FF_debt + ff_pfd_stk + ff_min_int_accum) - FF.ff_cash_st) as [Enterprise Value]
from ff_v2.ff_basic_af_v2 FF
where FF."date" =
( select MAX(FF2."date")
from ff_v2.ff_basic_af_v2 FF2
where FF2.fs_perm_sec_id=FF.fs_perm_sec_id
and FF.date <= FF2.date
)
and FF.fs_perm_sec_id in ('FT9TC5-S-GB','GPHC8W-S-GB','R85KLC-S-US')) t
group by t.fs_perm_sec_id
just use the Derived Table and Group by
Select fs_perm_sec_id,
SUM(Enterprise Value) EnterpriseValue
from (**your whole code**)
GROUP BY fs_perm_sec_id
use group by
How to use group by with union in t-sql
SELECT id,sum(*)
FROM ( SELECT id,
time
FROM dbo.a
UNION
SELECT id,
time
FROM dbo.b
)
GROUP BY id
DECLARE
#d1 DATE = '20151222'
, #fs_perm_sec_id VARCHAR(100) = 'GPHC8W-S-GB'
SELECT #fs_perm_sec_id, SUM([Enterprise Value])
FROM (
SELECT [Enterprise Value]
FROM (
SELECT
c.fs_perm_sec_id
, (c.p_price * s.p_com_shs_out) / 1000 AS [Enterprise Value]
, RowNum = ROW_NUMBER() OVER (ORDER BY s.[date] DESC)
from fp_v1.fp_basic_bd c
join fp_v1.fp_basic_sho s on s.fs_perm_sec_id = c.fs_perm_sec_id
left join edm_v1.edm_security_entity_map e on e.fs_perm_sec_id= c.fs_perm_sec_id
where c.[date] = #d1
and e.termination_date is null
and c.fs_perm_sec_id = #fs_perm_sec_id
) t
WHERE t.RowNum = 1
UNION ALL
SELECT FF_debt + ff_pfd_stk + ff_min_int_accum - ff_cash_st
FROM (
SELECT
ff.fs_perm_sec_id
, FF_debt
, ff_pfd_stk
, ff_min_int_accum
, FF.ff_cash_st
, RowNum = ROW_NUMBER() OVER (ORDER BY FF.[date] DESC)
FROM ff_v2.ff_basic_af_v2 FF
WHERE FF.[date] =
AND FF.fs_perm_sec_id = #fs_perm_sec_id
) t
WHERE t.RowNum = 2
) t
Here's my Count_query:
Declare #yes_count decimal;
Declare #no_count decimal;
set #yes_count=(Select count(*) from Master_Data where Received_Data='Yes');
set #no_count=(Select count(*) from Master_Data where Received_Data='No');
select #yes_count As Yes_Count,#no_count as No_Count,(#yes_count/(#yes_count+#no_count)) As Submission_Count
I am having trouble making joins on these two queries
This is the rest of the query:
Select Distinct D.Member_Id,d.Name,d.Region_Name, D.Domain,e.Goal_Abbreviation,
e.Received_Data, case when Received_Data = 'Service Not Provided' then null
when Received_Data = 'No' then null else e.Improvement end as
Percent_Improvement , case when Received_Data = 'Service Not Provided' then null
when Received_Data = 'No' then null else e.Met_40_20 end as Met_40_20
FROM (
select distinct member_Domains.*,
(case when NoData.Member_Id is null then 'Participating' else ' ' end) as Participating
from
(
select distinct members.Member_Id, members.Name, Members.Region_Name,
case when Domains.Goal_Abbreviation = 'EED Reduction' then 'EED'
When Domains.Goal_Abbreviation = 'Pressure Ulcers' then 'PRU'
when Domains.Goal_Abbreviation = 'Readmissions' then 'READ' else Domains.Goal_Abbreviation end as Domain from
(select g.* from Program_Structure as ps inner join Goal as g on ps.Goal_Id = g.Goal_Id
and ps.Parent_Goal_ID = 0) as Domains
cross join
(select distinct hc.Member_ID, hc.Name,hc.Region_Name from zsheet as z
inner join Hospital_Customers$ as hc on z.CCN = hc.Mcare_Id) as Members
) as member_Domains
left outer join Z_Values_Hospitals as NoData on member_Domains.member_ID = NoData.Member_Id
and Member_Domains.Domain = noData.ReportName) D
Left Outer JOIN
(SELECT B.Member_ID, B.Goal_Abbreviation, B.minRate, C.maxRate, B.BLine, C.Curr_Quarter, B.S_Domain,
(CASE WHEN B.Member_ID IN
(SELECT member_id
FROM Null_Report
WHERE ReportName = B.S_Domain) THEN 'Service Not Provided' WHEN Curr_Quarter = 240 THEN 'Yes' ELSE 'No' END) AS Received_Data,
ROUND((CASE WHEN minRate = 0 AND maxRate = 0 THEN 0 WHEN minRate = 0 AND maxRate > 0 THEN 1 ELSE (((maxRate - minRate) / minRate) * 100) END), .2) AS Improvement,
(CASE WHEN ((CASE WHEN minRate = 0 AND maxRate = 0 THEN 0 WHEN minRate = 0 AND maxRate > 0 THEN 1 ELSE (maxRate - minRate) / minRate END)) <= - 0.4 OR
maxRate = 0 THEN 'Yes' WHEN ((CASE WHEN minRate = 0 AND maxRate = 0 THEN 0 WHEN minRate = 0 AND maxRate > 0 THEN 1 ELSE (maxRate - minRate) / minRate END))
<= - 0.2 OR maxRate = 0 THEN 'Yes' ELSE 'No' END) AS Met_40_20
FROM (SELECT tab.Member_ID, tab.Measure_Value AS minRate, tab.Goal_Abbreviation, A.BLine, tab.S_Domain
FROM Measure_Table_Description AS tab INNER JOIN
(SELECT DISTINCT
Member_ID AS new_memid, Goal_Abbreviation AS new_measure, MIN(Reporting_Period_ID) AS BLine, MAX(Reporting_Period_ID)
AS Curr_Quarter
FROM Measure_Table_Description
WHERE (Member_ID > 1) AND (Measure_Value IS NOT NULL) AND (Measure_ID LIKE '%O%')
GROUP BY Goal_Abbreviation, Member_ID) AS A ON tab.Member_ID = A.new_memid AND tab.Reporting_Period_ID = A.BLine AND
tab.Goal_Abbreviation = A.new_measure) AS B FULL OUTER JOIN
(SELECT tab.Member_ID, tab.Measure_Value AS maxRate, tab.Goal_Abbreviation, A_1.Curr_Quarter
FROM Measure_Table_Description AS tab INNER JOIN
(SELECT DISTINCT
Member_ID AS new_memid, Goal_Abbreviation AS new_measure,
MIN(Reporting_Period_ID) AS BLine, MAX(Reporting_Period_ID)
AS Curr_Quarter
FROM Measure_Table_Description AS Measure_Table_Description_1
WHERE (Member_ID >1) AND (Measure_Value IS NOT NULL) AND (Measure_ID LIKE '%O%')
GROUP BY Goal_Abbreviation, Member_ID) AS A_1 ON tab.Member_ID = A_1.new_memid
AND tab.Reporting_Period_ID = A_1.Curr_Quarter AND
tab.Goal_Abbreviation = A_1.new_measure) AS C ON B.Member_ID = C.Member_ID
WHERE (B.Goal_Abbreviation = C.Goal_Abbreviation) ) E ON D.Member_Id = E.Member_ID AND d.Domain = E.S_Domain
ORDER BY D.Domain,D.Member_ID
How do I get a count of the 'yes'/ (count(yes)+count(no)) for each member_ID as column1 and also display the rank of each member_ID against all the member_IDs in the result as column2. I have come up with a query that generates the count for the entire table, but how do I restrict it each Member_ID.
Thanks for your help.
I haven't taken the time to digest your provided query, but if abstracted to the concept of having an aggregate over a range of data repeated on each row, you should look at using windowing functions. There are other methods, such as using a CTE to do your aggregation and then JOINing back to your detailed data. That might work better for more complex calculations, but the window functions are arguably the more elegant option.
DECLARE #MasterData AS TABLE
(
MemberID varchar(50),
MemberAnswer int
);
INSERT INTO #MasterData (MemberID, MemberAnswer) VALUES ('Jim', 1);
INSERT INTO #MasterData (MemberID, MemberAnswer) VALUES ('Jim', 0);
INSERT INTO #MasterData (MemberID, MemberAnswer) VALUES ('Jim', 1);
INSERT INTO #MasterData (MemberID, MemberAnswer) VALUES ('Jim', 1);
INSERT INTO #MasterData (MemberID, MemberAnswer) VALUES ('Jane', 1);
INSERT INTO #MasterData (MemberID, MemberAnswer) VALUES ('Jane', 0);
INSERT INTO #MasterData (MemberID, MemberAnswer) VALUES ('Jane', 1);
-- Method 1, using windowing functions (preferred for performance and syntactical compactness)
SELECT
MemberID,
MemberAnswer,
CONVERT(numeric(19,4),SUM(MemberAnswer) OVER (PARTITION BY MemberID)) / CONVERT(numeric(19,4),COUNT(MemberAnswer) OVER (PARTITION BY MemberID)) AS PercentYes
FROM #MasterData;
-- Method 2, using a CTE
WITH MemberSummary AS
(
SELECT
MemberID,
SUM(MemberAnswer) AS MemberYes,
COUNT(MemberAnswer) AS MemberTotal
FROM #MasterData
GROUP BY MemberID
)
SELECT
md.MemberID,
md.MemberAnswer,
CONVERT(numeric(19,4),MemberYes) / CONVERT(numeric(19,4),MemberTotal) AS PercentYes
FROM #MasterData md
JOIN MemberSummary ms
ON md.MemberID = ms.MemberID;
First thought is: your query is much, much too complicated. I have spent about 10 minutes now trying to make sense of it and haven't gotten anywhere, so it's obviously going to pose a long-term maintenance challenge to those within your organization going forward as well. I would really recommend you try to find some way of simplifying it.
That said, here is a simplified, general example of how to query on a calculated value and rank the results:
CREATE TABLE member (member_id INT PRIMARY KEY);
CREATE TABLE master_data (
transaction_id INT PRIMARY KEY,
member_id INT FOREIGN KEY REFERENCES member(member_id),
received_data BIT
);
-- INSERT data here
; WITH member_data_counts AS (
SELECT
m.member_id,
(SELECT COUNT(*) FROM master_data d WHERE d.member_id = m.member_id AND d.received_data = 1) num_yes,
(SELECT COUNT(*) FROM master_data d WHERE d.member_id = m.member_id AND d.received_data = 0) num_no
FROM member m
), member_data_calc AS (
SELECT
*,
CASE
WHEN (num_yes + num_no) = 0 THEN NULL -- avoid division-by-zero error
ELSE num_yes / (num_yes + num_no)
END pct_yes
FROM member_data_counts
), member_data_rank AS (
SELECT *, RANK() OVER (ORDER BY pct_yes DESC) AS RankValue
FROM member_data_calc
)
SELECT *
FROM member_data_rank
ORDER BY RankValue ASC;