I have a query which sums field 'value' from rows with foreign key value V1 and divides that sum with sum of the field 'value' from rows with foreign key value V2. Somehow I am getting wrong results. What am I doing wrong here?
SELECT
iv1.year,
1,
iv1.country_code,
SUM(iv1.value) / SUM(iv2.value) AS value, # Formula
'Added using stored procedure for creation of 1 indicator as ratio of 2 over 6 indicators' AS additional_info
FROM
indicators_values iv1
JOIN indicators i1 ON (i1.no_of_indicator IN('B1.1.2.3', 'B1.2.2.2')
AND iv1.indicator_id = i1.indicator_id
AND i1.extracted_from_file_type = 'consolidated-a')
JOIN indicators_values iv2 ON (iv2.country_code = iv1.country_code AND iv2.year = iv1.year)
JOIN indicators i2 ON (i2.no_of_indicator IN('B1.1.2.2', 'B1.1.2.3', 'B1.1.2.4', 'B1.2.2.1', 'B1.2.2.2', 'B1.2.2.3')
AND iv2.indicator_id = i2.indicator_id
AND i2.extracted_from_file_type = 'consolidated-a')
WHERE
1=1
AND iv1.country_code = 'AT'
AND i1.no_of_indicator IN('B1.1.2.3', 'B1.2.2.2')
AND i2.no_of_indicator IN('B1.1.2.2', 'B1.1.2.3', 'B1.1.2.4', 'B1.2.2.1', 'B1.2.2.2', 'B1.2.2.3')
GROUP BY
iv1.year, iv1.country_code;
I know that I am getting wrong results, because most of the results that I am getting are bigger than 1, and they should all be smaller than 1, since I should have in the denominator same values contained in the numerator, plus some additional ones. Please advise? Thanks!
Schematically (too lazy to understand your conditions - maybe something is missing or changed places):
SELECT iv.year,
iv.country_code,
( SUM(CASE WHEN i.no_of_indicator IN('B1.1.2.3', 'B1.2.2.2')
THEN iv.value
END)
/
SUM(CASE WHEN i.no_of_indicator IN('B1.1.2.2', 'B1.1.2.3', 'B1.1.2.4', 'B1.2.2.1', 'B1.2.2.2', 'B1.2.2.3')
THEN iv.value
END
) AS value
FROM indicators_values iv
JOIN indicators i ON iv.indicator_id = i.indicator_id
WHERE i.extracted_from_file_type = 'consolidated-a'
AND iv.country_code = 'AT'
GROUP BY iv.year, iv.country_code
PS. Divisor may formally be zero - take care not to get a division by zero error.
Related
First Stackoverflow question - so go easy on me :).
Hello, I am trying to flag items as "Attributed" using the following query that I have written. Essentially, if a patient ID has a PERSON_PROVIDER_RELATIONSHIP flag, they are given a 1 for that instance. If they have another type of flag (there are two other possible flags you can receive). Everything goes fine (the assigning of "1" to the instances of PERSON_PROVIDER_RELATIONSHIP), but then when I try to sum that custom column I created ("Attribution"), I get this error: (Column "Attribution" does not exist). I get this error whether I try to make another column that does the summing or when I add a "having" clause to the end where I state I only want to see records with a sum of >0. Any help would be appreciated here! I'm using MySQL to write this and am happy to provide any clarifying information.
select distinct c.empi_id as "Patient",
c.incurred_from_date as "Service Date",
(case when c.billing_organization_source_id IN ('xxxx','yyyy') then 1 else 0
end) as "In-Network Indicator",
(case when t.ref_record_type = 'PERSON_PROVIDER_RELATIONSHIP' then 1 else 0
end) as "Attribution",
(sum("Attribution") over (partition by c.empi_id)) as "Attribution Flag",
p.cleanprovidername as "Provider", t.ref_record_type
from ph_f_annotated_claim c
left outer join PH_F_Attribution_Component_Data_Point t
on t.empi_id = c.empi_id and t.population_id = c.population_id
inner join ph_d_personnel_alias a
on a.prsnl_id = t.prsnl_id
inner join xxxx_xxxx_xxxx_xxxx p
on a.prsnl_alias_id = p.NPI
where (c.bill_type_code like '33%'
or c.bill_type_code like '32%'
or c.bill_type_code like '033%'
or c.bill_type_code like '032%')
and c.source_description = 'MSSP Claims'
and c.incurred_from_date >= '2015-12-01'
and c.incurred_from_date <= '2017-01-31'
and c.population_id = '2feb2cb1-be55-4827-a21f-4e2ef1a40340'
and p.DegreeName IN ('MD','DO')
and a.prsnl_alias_type = 'NPI'
and p.PrimaryPHO = 'Yes'
group by c.empi_id, c.incurred_from_date, c.billing_organization_source_id,
p.cleanprovidername, t.ref_record_type
You can't use an aliased column name as an expression in the same SELECT clause. You have to do something like this:
sum(case when t.ref_record_type = 'PERSON_PROVIDER_RELATIONSHIP' then 1 else 0 end) over (partition by c.empi_id) as "Attribution Flag"
I have a system that collects data from production reports (CSV files) and puts them into a mySql DB.
I have an header table, that contain the production data of sequential report with same setting, and a table with the single reports, connected to the first one (trfCamRep.hdrId -> trfCamHdr.id).
I have a query to calculate the total report, the dubt and the faulty, and the maxTs. These datas are used in the visualizator.
The query is too slow, it requires 9sec.
Can you help me to speed up it?
SET #maxId:=(SELECT MAX(id) FROM trfCamHdr WHERE srcCod='7');
UPDATE trfCamHdr AS hdr
LEFT JOIN (SELECT hdrF.id,COUNT(*) AS nTot,
SUM(IF(res=1,1,0)) AS nWrn,SUM(IF(res=2,1,0)) AS nKO,
MAX(ts) AS maxTS
FROM trfCamHdr AS hdrF
JOIN trfCamRep AS repF ON repF.hdrId=hdrF.id
WHERE clcEnd=0 AND srcCod='7'
GROUP BY hdrF.id) AS valT ON valT.id=hdr.id
SET hdr.clcEnd=IF(hdr.id<#maxId,1,0),
hdr.nTot=valT.nTot,
hdr.nWrn=valT.nWrn,
hdr.nKO=valT.nKO,
hdr.maxTS=valT.maxTS
WHERE hdr.id>=0 AND hdr.clcEnd=0 AND hdr.srcCod='7';
Note trfCamHdr has these columns:
id (primary key)
clcEnd : flag of end calculation (the last remain to 0 because in progress)
nTot : elements with this header
nWrn : elements with res = 1
nKO : elements with res = 2
maxTs : TS of the last element
trfCamRep has these columns:
hdrId (refer to id of trfCamHdr)
res : 0 good, 1 dubt, 2 fault
ts : report timestamp
I'd take this out:
SET #maxId:=(SELECT MAX(id) FROM trfCamHdr WHERE srcCod='7');
And any allusions to the MaxId variable, I believe it to be redundant.
Everything you do will be lower than the max id, and it will take time to calculate if its a big table. You are already checking for srcCod = 7, so it isn't necessary.
In fact, it would miss the update on the one with the actual max id, which is not what I believe you want.
Your left join will also update all other rows in the table with NULL, is that what you want? You could switch that to an inner join, and if your rows are already null, they will just get left alone, rather than getting updated with NULL again.
Then you could just switch out this:
SET
hdr.clcEnd = IF(hdr.id < #maxId, 1, 0),
To
SET
hdr.clcEnd = 1,
Here is the rewritten thing, as always, back your data up before trying:
UPDATE trfCamHdr AS hdr
INNER JOIN
(SELECT
hdrF.id,
COUNT(*) AS nTot,
SUM(IF(res = 1, 1, 0)) AS nWrn,
SUM(IF(res = 2, 1, 0)) AS nKO,
MAX(ts) AS maxTS
FROM
trfCamHdr AS hdrF
JOIN trfCamRep AS repF ON repF.hdrId = hdrF.id
WHERE
clcEnd = 0 AND srcCod = '7'
GROUP BY hdrF.id) AS valT ON valT.id = hdr.id
SET
hdr.clcEnd = 1,
hdr.nTot = valT.nTot,
hdr.nWrn = valT.nWrn,
hdr.nKO = valT.nKO,
hdr.maxTS = valT.maxTS
WHERE
hdr.id >= 0 AND hdr.clcEnd = 0
AND hdr.srcCod = '7';
I found the solution: I created a KEY on hdrId column and now the query requires 0.062s.
See the SQL query below:
SELECT *
FROM
(SELECT
h.hotel_id AS id,h.hotel_city AS city,h.hotel_name AS hotelname,
h.hotel_star AS hotelcat, hwd.double_spl_rate, hwd.third_party_rate,
hwd.extra_bed_spl_rate, hwd.meal_plan_spl,
hwd.third_party_extra_bed, hwd.third_party_meal_plan,
hwd.room_category, hrd.hotel_rate_from, hrd.hotel_rate_to
FROM
hotels_list AS h
INNER JOIN
hotel_rate_detail AS hrd ON h.hotel_id = hrd.hotels_id
INNER JOIN
hotel_week_days AS hwd ON hrd.hotel_id = hwd.h_id
WHERE
(('2015-07-31' BETWEEN hrd.hotel_rate_from AND hrd.hotel_rate_to)
OR
('2015-08-01' BETWEEN hrd.hotel_rate_from AND hrd.hotel_rate_to)
)
AND (h.hotel_city = '1')
AND (hwd.double_spl_rate != 0 OR hwd.third_party_rate != 0)
AND (h.hotel_star = '4')
ORDER BY
hwd.double_spl_rate, hwd.third_party_rate ASC) AS result_table
GROUP BY
result_table.id
ORDER BY
result_table.double_spl_rate, result_table.third_party_rate ASC
LIMIT 0,5;
OUTPUT is attached below:
In the above output there are two columns double_spl_rate and third_party_rate which can be either 0 or a value greater than zero.
How can I create a virtual column alias which only contain values greater the zero. Let us suppose the column is final_rate which will contain values as
id | final_rate
533 | 3776
9228 | 3000
Yes, you can do this like so:
select
id,
case
when coalesce(double_spl_rate,0) = 0
then third_party_rate
else double_spl_rate
end as final_rate
from table
The coalesce operator will set double_spl_rate to 0 if it's null, and the case expression will return third_party_rate if double_spl_rate is 0.
If double_spl_rate cannot be null you can skip the coalesce part.
Note that the code above will always prefer the value in double_spl_rate and disregard the other value if both values are greater than 0. If you don't want this you could extend the logic in the case expression to account for that and return the sum of the values instead. Or you could simply just return third_party_rate + double_spl_rate in all cases.
I have an expression that calculates a value in a textbox. I would like, at the end of the report, to have a total of all the fields in that textbox. However, the expression uses named fields from the query, which are totaled also.
=SUM(Fields!Total_Defective__.Value) / SUM(Fields!sales_Dollars.Value)
Total_Defective__ and sales_Dollars are totaled at the end of the report. So when I put that expression in the total field for that column, it performs the calculation on the totals for the other columns. This produces a incorrect result, since its based on the totals of the other fields. what I'm trying to do is sum the column. I tried Use a summary field in an expression in SSRS reports but this only gives me the row above the total, and you cannot aggregate by it.
So the report looks like this:
The COQ total colummn is taking the total of Defective $ / sales. I would like it to add the column (COQ) to be $0.39
Here is what the query looks like:
--Prod Qty
SELECT Division as 'division', SUM(prodtable.qtysched)as 'qty',rtrim(Ltrim(itemgroupid)) as 'itemGroup'
into #SCHED
FROM MiscReportTables.dbo.PlantDivisions
inner join prodtable on prodtable.dimension2_ = MiscReportTables.dbo.PlantDivisions.Division
WHERE PlantID IN (#plantid)
and SCHEDDATE between #start and #end
Group by itemgroupid,MiscReportTables.dbo.PlantDivisions.Division
--sales qty
Select Division as 'Division', SUM(SALESQTY) as 'salesQTY',rtrim(Ltrim(salesline.itemgroupid)) as 'itemGroup'
into #salesQty
FROM MiscReportTables.dbo.PlantDivisions
inner join prodtable on prodtable.dimension2_ = MiscReportTables.dbo.PlantDivisions.Division
inner join SalesLine on SalesLine.InventrefId = ProdTable.ProdiD
WHERE PlantID IN (#plantid)
and SCHEDDATE between #start and #end
Group By Division,salesLine.itemgroupid
--SALES Dollars
Select Division as 'Division',
(SUM(SALESQTY) - REMAINSALESFINANCIAL) * (SalesPrice / PriceUnit) as 'sales$',
rtrim(Ltrim(salesline.itemgroupid)) as 'itemGroup'
into #salesDollars
FROM MiscReportTables.dbo.PlantDivisions
inner join prodtable on prodtable.dimension2_ = MiscReportTables.dbo.PlantDivisions.Division
inner join SalesLine on SalesLine.InventrefId = ProdTable.ProdiD
WHERE PlantID IN (#plantid)
and SCHEDDATE between #start and #end
Group By Division,salesLine.itemgroupid,REMAINSALESFINANCIAL,SalesPrice,PriceUnit
SELECT
dbo.TQMNCR.NCRID,
dbo.TQMPlantTable.PlantName AS 'Division',
RTRIM(LTRIM(dbo.INVENTTABLE.ITEMGROUPID)) AS 'Item Process/Group',
dbo.TQMNCRDEFECTTYPECODES.QTY AS 'Defective Qty',
CASE CATYPE
WHEN 0 THEN
(CASE WHEN dbo.SALESLINE.SALESID = ''
THEN ISNULL((PRICE * (PERCENTEXT / 100)) / NULLIF(dbo.INVENTTABLEMODULE.PRICEUNIT, 0), 0) * dbo.TQMNCRDEFECTTYPECODES.QTY
ELSE ISNULL((SALESPRICE * (PERCENTEXT / 100)) / NULLIF(dbo.SALESLINE.PRICEUNIT, 0), 0) * dbo.TQMNCRDEFECTTYPECODES.QTY END)
WHEN 2 THEN
(CASE WHEN dbo.TQMNCR.SALESID = ''
THEN ISNULL((PRICE * (PERCENTINT / 100)) / NULLIF(dbo.INVENTTABLEMODULE.PRICEUNIT, 0), 0) * dbo.TQMNCRDEFECTTYPECODES.QTY
ELSE ISNULL((SALESPRICE * (PERCENTINT / 100)) / NULLIF(dbo.SALESLINE.PRICEUNIT, 0), 0) * dbo.TQMNCRDEFECTTYPECODES.QTY END)
ELSE 0 END AS 'Total Defective $',
dbo.PRODTABLE.PRODPOOLID
,#SCHED.qty,
(#SCHED.qty - dbo.TQMNCRDEFECTTYPECODES.QTY) / #SCHED.qty as 'First Pass Yield',
#salesQty.salesQty as 'Sales Quantity',
#salesDollars.sales$ as 'sales Dollars'
FROM
dbo.TQMNCR LEFT OUTER JOIN
dbo.TQMDISPOSITION ON dbo.TQMNCR.DISPOSITIONID = dbo.TQMDISPOSITION.DISPOSITIONID LEFT OUTER JOIN
dbo.TQMCA_TABLE ON dbo.TQMCA_TABLE.NCRID = dbo.TQMNCR.NCRID LEFT OUTER JOIN
dbo.TQMNCRDEFECTTYPECODES ON dbo.TQMNCR.NCRID = dbo.TQMNCRDEFECTTYPECODES.NCRID LEFT OUTER JOIN
dbo.TQMPlantTable ON TQMPlantTable.PlantID = dbo.TQMNCR.PlantID LEFT OUTER JOIN
dbo.INVENTTABLE ON dbo.TQMNCR.ITEMID = dbo.INVENTTABLE.ITEMID LEFT OUTER JOIN
dbo.INVENTTABLEMODULE ON dbo.INVENTTABLE.ITEMID = dbo.INVENTTABLEMODULE.ITEMID AND MODULETYPE = 2 LEFT OUTER JOIN
dbo.SALESLINE ON dbo.SALESLINE.SALESID = dbo.TQMNCR.SALESID AND dbo.SALESLINE.ITEMID = dbo.TQMNCR.ITEMID LEFT OUTER JOIN
dbo.PRODTABLE ON dbo.TQMNCR.PRODID = dbo.PRODTABLE.PRODID
inner join #sched on #sched.itemGroup = INVENTTABLE.itemgroupid
inner join #salesQty on #salesQty.itemGroup = INVENTTABLE.itemgroupid
inner join #salesDollars on #salesDollars.itemgroup = INVENTTABLE.itemgroupid
WHERE
SCHEDDATE between #start and #end
AND
dbo.TQMNCR.PlantID IN (#plantid)
ORDER BY dbo.INVENTTABLE.ITEMGROUPID, dbo.TQMPlantTable.PlantName
drop table #sched
drop table #SalesQty
drop table #salesDollars
and here's what the result set looks like:
The report is grouped by Item_Process,Division,Total_Defective
You could try adding your COQ field as a new Calculated Field in your dataset. Doing this will perform the calculation at dataset level, rather than Tablix grouping level.
Lets say you've called this new field "COQ".
Then in your total row, have the expression Sum(Fields!COQ.Value) as your total.
This should perform the calculation for each row's COQ first, then sum the result in the total row.
EDIT: The above will work if your dataset were grouped exactly as your table will be. When this is not the case (as you've indicated) and your table in SSRS is actually grouped from a more granular dataset, you can total your groups using the expression below:
=Sum(IIF(Sum(Fields!sales_Dollars.Value,"YOURGROUPNAME") > 0,
Sum(Fields!Total_Defective__.Value,"YOURGROUPNAME") /
Sum(Fields!sales_Dollars.Value,"YOURGROUPNAME"), 0))
This should evaluate the calculation within each member of the GROUP BY, and then SUM the result of the calculation across the entire table/dataset.
I beleive your requirement is beyond the capabilities of SSRS alone. I would move the grouping to the SQL dataset and (after grouping to the 9 "detail" rows in your example) I would calculate COQ in that dataset e.g.
SELECT *
, Total_Defective / Sales AS COQ
FROM (
SELECT
MyGroupColumns
, SUM ( Total_Defective ) AS Total_Defective
, SUM ( Sales ) AS Sales
FROM MyTable
GROUP BY
MyGroupColumns
) D1
Then SSRS can just present the detail COQ for the 9 rows output from the dataset, and you can use an SSRS Sum() function to get COQ for your Total row.
You should be able to do this with
=SUM(Fields!Total_Defective__.Value/Fields!sales_Dollars.Value)
So that it divides each value, then sums rather than summing the values before dividing.
EDIT: if you get divide by zero errors you can add the following to Report - Report Properties - code:
Public Function Quotient(ByVal numerator As Decimal, denominator As Decimal) As Decimal
If denominator = 0 Then
Return 0
Else
Return numerator / denominator
End If
End Function
(Ref: http://williameduardo.com/development/ssrs/ssrs-divide-by-zero-error/)
The enter the formula as
=SUM(code.Quotient(Fields!Total_Defective__.Value,Fields!sales_Dollars.Value)
Then you should get the desired result with relatively short code in your expression.
I've got a rather large query that is trying to get a list of carriers and compare the amount of insurance they have on record to identify carriers that do not meet a minimum threshold. If I run the select query it works just fine with no errors. But when I try to use it for an insert into a table it returns this error message
[Err] 1366 - Incorrect decimal value: '' for column '' at row -1
I have to use the cast as decimal at the bottom of this query because the value that is being stored in the database is a varchar and I cannot change that.
Anyone have any ideas?
set #cw_days = 15;
INSERT INTO carrier_dnl (carrier_id, dnl_reason_id, status_id)
SELECT work_cw_carrier_status_update.carrier_id, company_dnl_schema.dnl_reason_id,
CASE
WHEN work_cw_carrier_status_update.comparison_date > #cw_days THEN 1
ELSE 4
END as status
FROM work_cw_carrier_status_update
JOIN company_dnl_schema
ON company_dnl_schema.dnl_reason_id = 51
LEFT OUTER JOIN carrier_insurance
ON carrier_insurance.carrier_id = work_cw_carrier_status_update.carrier_id
WHERE ifnull(carrier_insurance.insurance_type_id,4) = 4
AND date(now()) BETWEEN IFNULL(carrier_insurance.insurance_effective_date,DATE_SUB(now(),INTERVAL 1 day)) AND IFNULL(carrier_insurance.insurance_expiration_date,DATE_ADD(now(),INTERVAL 1 day))
AND CASE WHEN NULLIF(carrier_insurance.insurance_bipdto_amount,'') is null THEN 0 < company_dnl_schema.value
ELSE
ifnull(cast(replace(carrier_insurance.insurance_bipdto_amount, '*','') as decimal),0) < company_dnl_schema.value
END
AND ( work_cw_carrier_status_update.b_bulk = 0 OR work_cw_carrier_status_update.b_bulk = 1 )
AND ( work_cw_carrier_status_update.b_otr = 1 OR work_cw_carrier_status_update.b_ltl = 1
OR work_cw_carrier_status_update.b_dray = 1 OR work_cw_carrier_status_update.b_rail = 1
OR work_cw_carrier_status_update.b_intermodal = 1 OR work_cw_carrier_status_update.b_forwarder = 1
OR work_cw_carrier_status_update.b_broker = 1 )
group by work_cw_carrier_status_update.carrier_id;`
If the select seems to work, then there are two possible problems. The first is that the select doesn't really work and the problem appears further down in the data. Returning one or a handful of rows is not always the same as "working".
The second is an incompatibility with the types for the insert. You can try to use silent conversion to convert the values in the select to numbers:
SELECT work_cw_carrier_status_update.carrier_id + 0, company_dnl_schema.dnl_reason_id + 0,
(CASE WHEN work_cw_carrier_status_update.comparison_date > #cw_days THEN 1
ELSE 4
END) as status
This may look ugly, but it is not nearly as ugly as storing ids as strings in one table and as numbers in another.