I'm fairly new to ssrs and I'm trying to creat a report with a sub-report which e.g. returns 3 fields / columns.
When I export this to excel it reads
A1 B1 C1
100 50 100
When there's no data / dataset returns no records all cells A to C are merged to one cell?
Which makes processing the file a real pain...
I've tried the norowsmessage but then I get one value in the merged cells.
Can't remember I had this with Crystal Reports?
Is there something I can do to always return the sub-report with the 3 columns in it so my layout is retained?
Thanks in advance,
Mike
I've fixed it by using a Union statement in my SQL string:
SELECT - SUM(QTY) AS EXPR1, - SUM(ENTEREDVALUE) AS EXPR2, - SUM(LINEAMOUNTMST) AS EXPR3
FROM DBS_SUPERVISOR.STOCKTRANS
WHERE (DATASET = 'CAT') AND (ITEMNUMBER = :myitem) AND (DATEPHYSICAL >= :VanDatum) AND (DATEPHYSICAL <= :TotDatum) AND (STREFERENCE = 0) AND
(DCTYPE = 1) AND (STATUSOUTFLOW = 1) AND (DCGROUP = 'GROUPX')
GROUP BY ITEMNUMBER
UNION ALL
SELECT 0 AS EXPR1, 0 AS EXPR2, 0 AS EXPR3
FROM SYS."DUAL"
WHERE (NOT EXISTS
(SELECT QTY AS EXPR1
FROM DBS_SUPERVISOR.STOCKTRANS STOCKTRANS_1
WHERE (DATASET = 'CAT') AND (ITEMNUMBER = :myitem) AND (DATEPHYSICAL >= :VanDatum) AND (DATEPHYSICAL <= :TotDatum) AND (STREFERENCE = 0)
AND (DCTYPE = 1) AND (STATUSOUTFLOW = 1) AND (DCGROUP = 'GROUPX')))
This way if the top part doesn't return a row the bottom part will return 3 columns with 0
Regards,
Mike
Related
I'm having this issue
Now, I'm having this table
Code
FirstNo
LastNo
Date_input
ABC1234
12
34
2022/06/06
ABCD5678
56
78
2022/07/07
ABCD9111
91
11
2022/07/07
DEF1234
12
34
2022/06/06
DEF5678
56
78
2022/07/07
Then, I want to return 2 random number (these 2 number is from 00 to 99) which will be taken from front-end. Lets call them Random1 and Random2.
Now, when the query running, it will run from record 1 --> final
If whenever the FirstNo = Random1, then the next record will take the condition of FirstNo = Random2. Then, at the next record, it will return to get the condition of FirstNo = Random1.
For example, Random1 = 56, Random2 = 91, and the table as above
First record: FirstNo != 56, move to the next row.
Second record: FirstNo = 56.
Third record: (Because of at the previous record, FirstNo equal Random1 (56), this record will get Random2 instead) FirstNo = 91.
Fourth record: Back to Random1, .....
So, I'm figuring out something like:
SELECT * FROM CODE_DEX WHERE FirstNo = #Random1
SELECT * FROM CODE_DEX WHERE FirstNo = #Random2
I haven't have any idea how to joining these 2. I can create a column ISTRUE or something to Declare and Set in SQL, but I don't think I can use IF in the middle of the sql query.
Thank you so much
Based on stated requirement
If the prior row value for FirstNo ordered by date is Random1 then return random2 for FirstNo
You would do that like this in SQL
SELECT Code,
CASE WHEN LAG(FirstNo,1) OVER (ORDER BY Date_Input) = Random1
THEN Random2
ELSE FirstNo END AS FirstNo,
LastNo,
Date_input
FROM sometableyoudidnotname
ORDER BY Date_input
You can select:
next value, with the LEAD window function
previous value, with the LAG window function
then filter out all rows which don't have "Random1" and "Random2" values in consecutive rows:
SET #Random1 = 56;
SET #Random2 = 91;
WITH cte AS (
SELECT *,
LAG(FirstNo) OVER(ORDER BY Code, Date_input) AS PrevNo,
LEAD(FirstNo) OVER(ORDER BY Code, Date_input) AS NextNo
FROM tab
)
SELECT Code,
FirstNo,
LastNo,
Date_input
FROM cte
WHERE (FirstNo = #Random1 AND NextNo = #Random2)
OR (FirstNo = #Random2 AND PrevNo = #Random1)
Check the demo here.
A snapshot of my DB
I want to get count of pcl_No present in a specified range( SUM(tv_land + tv_imp))
I have written a query but I am getting Invalid use of group error
select
count(CASE WHEN sum(tv_land+tv_imp) BETWEEN 0 AND 10000 THEN 1 END) as count0_10000
from
tax_l2006
where red_date = 0
GROUP BY pcl_no
Sample Output
0-10000 10000-20000 30000-40000 >40000
2 3 1 8
I think you just want:
select count(CASE WHEN tv_land + tv_imp BETWEEN 0 AND 10000 THEN 1 END) as count0_10000
from tax_l2006
where red_date = 0;
I would write this in MySQL more simply as:
select sum( (tv_land + tv_imp) between 0 and 10000 ) as count0_10000
from tax_l2006
where red_date = 0;
MySQL treats a true boolean as "1" in a numeric context and "0" for false, so summing the boolean is counting the number of times it is true.
You can follow the same pattern for the rest of the columns.
If pcl_no is not unique and you need to sum the values, then you would use a subquery:
select sum(total between 0 and 10000) as count0_10000
from (select pcl_no, sum(tv_land + tv_imp) as total
from tax_l2006
where red_date = 0
group by pcl_no
) p;
However, your data suggests that the column is unique, so the additional aggregation is not necessary.
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.
Were are facing a big problem with string length control in SQL Server 2008.
A brief recap of our system:
import data in a persistent staging area from *.txt file (semicolon as separator), using bulk insert in SQL Server environment;
in PSA table all columns are varchar(MAX);
cleaning operations using insert statement based on a select with multiple where conditions.
The problem we deal with is on a single column type and length, in fact in data warehouse level it has to be numeric and its lengths must not exceed 13 digits.
The select is the following:
select cast(LTRIM(RTRIM(data_giacenza)) as numeric),
LTRIM(RTRIM(codice_socio)),
LTRIM(RTRIM(codice_gln)),
LTRIM(RTRIM(tipo_gln)),
LTRIM(RTRIM(codice_articolo_socio)),
LTRIM(RTRIM(codice_ean_prodotto)),
LTRIM(RTRIM(codice_ecat_prodotto)),
LTRIM(RTRIM(famiglia)),
LTRIM(RTRIM(marca)),
LTRIM(RTRIM(classificazione_liv_1)),
LTRIM(RTRIM(classificazione_liv_2)),
LTRIM(RTRIM(classificazione_liv_3)),
LTRIM(RTRIM(classificazione_liv_4)),
LTRIM(RTRIM(modello)),
LTRIM(RTRIM(descrizione_articolo)),
cast(LTRIM(RTRIM(giacenza)) as numeric),
cast(LTRIM(RTRIM(acquistato)) as numeric), 'X' FROM psa_stock a
where EXISTS
(
SELECT 0
FROM(
SELECT
data_giacenza
,codice_socio
,codice_gln
,codice_articolo_socio
FROM psa_stock
where
LEN(LTRIM(RTRIM(data_giacenza))) = 8 and LEN(LTRIM(RTRIM(codice_socio))) = 3
and LEN(LTRIM(RTRIM(codice_gln))) = 13 and LEN(LTRIM(RTRIM(tipo_gln))) = 3
and LEN(LTRIM(RTRIM(codice_articolo_socio))) <= 15
and (LEN(LTRIM(RTRIM(codice_ean_prodotto))) <= 13 or LEN(ISNULL(codice_ean_prodotto, '')) = 0)
and (LEN(LTRIM(RTRIM(codice_ecat_prodotto))) = 9 or LEN(ISNULL(codice_ecat_prodotto, '')) = 0)
and LEN(LTRIM(RTRIM(famiglia))) = 2
and (LEN(LTRIM(RTRIM(marca))) <= 20 or LEN(ISNULL(marca, '')) = 0)
and (LEN(LTRIM(RTRIM(modello))) <= 30 or LEN(ISNULL(modello, '')) = 0)
and (LEN(LTRIM(RTRIM(descrizione_articolo))) <= 50 or LEN(ISNULL(descrizione_articolo, '')) = 0)
and LEN(LTRIM(RTRIM(giacenza))) <= 5
and LEN(LTRIM(RTRIM(acquistato))) <= 5
and (LEN(LTRIM(RTRIM(classificazione_liv_1))) <= 15 or LEN(ISNULL(classificazione_liv_1, '')) = 0)
and (LEN(LTRIM(RTRIM(classificazione_liv_2))) <= 15 or LEN(ISNULL(classificazione_liv_2, '')) = 0)
and (LEN(LTRIM(RTRIM(classificazione_liv_3))) <= 15 or LEN(ISNULL(classificazione_liv_3, '')) = 0)
and (LEN(LTRIM(RTRIM(classificazione_liv_4))) <= 15 or LEN(ISNULL(classificazione_liv_4, '')) = 0)
and ISNUMERIC(ltrim(rtrim(REPLACE(data_giacenza, ' ', '')))) = 1
and ISNUMERIC(ltrim(rtrim(REPLACE(codice_gln, ' ', '')))) = 1
and ISNUMERIC(LTRIM(RTRIM(REPLACE(giacenza, ' ', '')))) = 1 and charindex(',', giacenza) = 0
and ISNUMERIC(LTRIM(RTRIM(REPLACE(acquistato, ' ', '')))) = 1
and ISNUMERIC(ltrim(rtrim(REPLACE(codice_ean_prodotto, ' ', '')))) = 1
and ISNUMERIC(ltrim(rtrim(REPLACE(codice_ecat_prodotto, ' ', '')))) = 1
and codice_socio in (select codice_socio from ana_socio)
and tipo_gln in (select tipo from ana_gln)
and codice_gln in (select codice_gln from dw_key_gln)
group by
data_giacenza
,codice_socio
,codice_gln
,codice_articolo_socio
having COUNT (*) = 1
) b
where
a.data_giacenza = b.data_giacenza and
a.codice_articolo_socio = b.codice_articolo_socio and
a.codice_socio = b.codice_socio and
a.codice_gln = b.codice_gln)
The critical field is codice_ean_prodotto.
In fact, it allows to consider also values as SEAGAT7636490026751,NE20000003039,NE20000002168 which are not numeric and, the first, overlap maximum dimensions.
As result, the insert statement gives back
String o binary data would be truncated
error and fails the insertion.
Thanks in advance! I look forward your help!!!
Enrico
Have you tried executing that query, and adding codice_ean_prodotto = 'NE20000003039' to the where clause? Be sure that these are the actual field that is giving you the problem. If the select returns a row with that where clause, then something's wrong with the logic.
I'm leaning towards your having COUNT (*) = 1 clause in the EXISTS subquery - is it possible to have more than one record for these specific keys? As long as your PK is made up of those 4 fields (data_giacenza, codice_articolo_socio, codice_socio, codice_gln), you shouldn't need the GROUP BY and HAVING clauses at all. If you're not joining on your primary key, it could be that it is the culprit.
It's hard to tell without seeing your data model, however.
I figured out what was wrong.
In the inner select, we were excluding from the selection all records not respecting format constraints and duplication (the meaning of count(*)=1), extracting only the PK of the destination table.
But when selecting with PK we retrieve also those record that were duplicates, but were excluded by the format constraint, leading the insert to error due to dimension issues.
Now I divided the steps:
Duplicates lookup and deletion
Selection with format constraints
It works!