SQL Reporting Services - Can I Sum on field that contains expression? - sql

If I have a field in my SQL 2008 report that is generated via expression (meaning not directly from a dataset) should I be able to SUM it? Can I reference the field in a subsequent expression somehow - like by referencing the box name?

Your question isn't completely clear... but I'll take a stab at it.
Do you mean something like this:
SELECT SUM(GET_RANDOM_NUMBER()) as randomSum
FROM Table_That_Has_Infinite_Rows
WHERE rowId BETWEEN 3 AND 8
This will sum 6 numbers (because the range of a BETWEEN statement is inclusive on both ends).
You won't be able to reference the field alias 'immediately' in the WHERE clause -
SELECT SUM(GET_RANDOM_NUMBER()) as randomSum
FROM Table_With_One_Row
WHERE randomSum > 5 -- throws error, field 'does not exist'
However, it will be available in ORDER BY and GROUP BY clauses, and also if you wrap the query in something else (CTE, inline table, etx);
SELECT SUM(GET_RANDOM_NUMBER()) as randomSum
FROM Table_With_Thousand_Rows
GROUP BY randomSum -- although this won't have any apparent effect here

Related

Why do I have to group by every column in redshift?

I had a query made on aurora sql, it was working nice, but now I need to do the same in redshift, but when I do so, it throws an error asking me to group by by every column, but obviously I don't want that.
This is the query:
select
rut,
name,
id,
sum(cantidad_retornos) as cantidad_retornos,
sum(cantidad_aceptadas) as cantidad_aceptadas,
sum(cantidad_auto_accept) as cantidad_auto_accept,
sum(cantidad_rechazadas) as cantidad_rechazadas,
sum(cantidad_aceptadas) - sum(cantidad_auto_accept) as cantidad_aceptadas_manual,
coalesce((sum(cantidad_aceptadas) - sum(cantidad_auto_accept)) / nullif(sum(cantidad_aceptadas),0)) as per_aceptadas_manual,
coalesce(sum(cantidad_auto_accept) / nullif(sum(cantidad_aceptadas),0),0) as per_aceptadas_auto,
coalesce(sum(cantidad_rechazadas) / nullif(sum(cantidad_retornos),0),0) AS rechazo_per,
case
when coalesce(sum(cantidad_rechazadas) / nullif(sum(cantidad_retornos),0) ,0) < 0.1 or cantidad_retornos < 10 then 'Confiable'
when coalesce(sum(cantidad_rechazadas) / nullif(sum(cantidad_retornos),0),0) >= 0.1 and coalesce(sum(cantidad_rechazadas) / nullif(sum(cantidad_retornos),0),0) < 0.5 then 'Estándar'
when coalesce(sum(cantidad_rechazadas) / nullif(sum(cantidad_retornos),0),0) >= 0.5 then 'Poco confiable'
else 'Sin clasificar'
end as nivel_confianza
from table
where 1=1
group by id, name, rut
I tried to group by every column, but it doesn't throw the result that I need
The error that I get:
ERROR: column "reporte_sellers_date.cantidad_retornos" must appear in the GROUP BY clause or be used in an aggregate function
If I group by the third column, it throws the same error but with the column number 4
In the first option in the CASE statement you have or cantidad_retornos without any aggregating function such as SUM(). This is why Redshift is saying it needs to be in a group by. You also alias this name to the sum of the column of the same name. So the is a choice the database needs to make about which one to use - the source column or the aggregate. It looks like Aurora is choosing the aggregate but Redshift is choosing the source column.
Using the same name for an aggregate as a source column is not a good idea as you are relying on the query compiler to make a choice for you. This means the query can break when the compiler is updated or if you port the query to a different database.
To fix this you can either add the SUM() aggregation to the use of cantidad_retornos in the CASE statement or use the aggregate from above in the query but give it a unique name.

How to use aggregate function to filter a dataset in ssrs 2008

I have a matrix in ssrs2008 like below:
GroupName Zone CompletedVolume
Cancer 1 7
Tunnel 1 10
Surgery 1 64
ComplatedVolume value is coming by a specific expression <<expr>>, which is equal to: [Max(CVolume)]
This matrix is filled by a stored procedure that I am not supposed to change if possible. What I need to do is that not to show the data whose CompletedVolume is <= 50. I tried to go to tablix properties and add a filter like [Max(Q9Volume)] >= 50, but when I try to run the report it says that aggregate functions cannot be used in dataset filters or data region filters. How can I fix this as easy as possible?
Note that adding a where clause in sql query would not solve this issue since there are many other tables use the same SP and they need the data where CompletedVolume <= 50. Any help would be appreciated.
EDIT: I am trying to have the max(Q9Volume) value on SP, but something happening I have never seen before. The query is like:
Select r.* from (select * from results1 union select * from results2) r
left outer join procedures p on r.pid = p.id
The interesting this is there are some columns I see that does not included by neither results1/results2 nor procedures tables when I run the query. For example, there is no column like Q9Volume in the tables (result1, result2 and procedures), however when I run the query I see the columns on the output! How is that possible?
You can set the Row hidden property to True when [Max(CVolume)] is less or equal than 50.
Select the row and go to Row Visibility
Select Show or Hide based on an expression option and use this expression:
=IIF(
Max(Fields!Q9Volume.Value)<=50,
True,False
)
It will show something like this:
Note maximum value for Cancer and Tunnel are 7 and 10 respectively, so
they will be hidden if you apply the above expression.
Let me know if this helps.

Sum of distinct values in field SSRS 2005

I'm working on SSRS report builder that is using a dataset calling a SQL Server 2000 database.
The query is getting sums of a few different fields and is also pulling out all records that have to do with that client number. I want to get the sum of the sum but it is way over because of the detail rows. Basically what I want is the sum of the distinct sum column values.
=Sum(Fields!tot.Value, "table1_Group3")
I saw that you can get sums by the groups and I tried the expression above but it comes back with an error:
The Value expression for the textbox 'tot' has a scope parameter that is not
valid for an aggregate function...
table1_Group3 is the name of the group that holds the sum value in the report.
Any suggestions on how to get the distinct values to sum them in this report.
=Sum(Fields!tot.Value, "table1_Group3")
The code above will give you the sum of "tot" for all rows in the current "table1_Group3." This means that this expression only makes sense somewhere within table1_Group3. Otherwise, SSRS doesn't know which is the current instance of that group.
Sounds like you would like to sum this value across multiple groups, but only take one "tot" from each instance of the group. (Are you sure that all rows in that group will have the same "Tot?")
If tot is the total of other fields in your returned data, then simply add those up in your formula. This may have the added benefit of simplifying your SQL query as well.
Some other options that could work:
- Change your SQL query so that only one row per group gets the Tot field set.
- Use Embedded code in the report to keep a running total which is added to only once per group, such as in the group header.
(If upgrading to 2008R2 SSRS is an option, then the Lookup function could be used here, maybe even to look back at the same dataset.)
change the query/ dataset to sum(distinct tot) using the temp table on the sql server
I suppose you need to write sum(distinct columnName).

Parameters in Microsoft Access

I'm really confused with how parameters work in Microsoft Access. I know that parameters are supposed to be used to allow a user to type in values when the query is run - instead of having to modify the query for each instance.
So, let's use the following example.
SELECT countyTable.countyName, Sqr((69.1*(46.47-avgLatitude))^2+(69.1*(-90.17-avgLongitude)*Cos(avgLatitude/57.3))^2) as Distance
FROM countyTable
WHERE ((([avgLatitude]-5)<46.47) AND (([avgLatitude]+5)>46.47) AND (([avgLongitude]-5)<-90.17) AND (([avgLongitude]+5)>-90.17))
ORDER BY Sqr((69.1*(46.47-avgLatitude))^2+(69.1*(-90.17-avgLongitude)*Cos(avgLatitude/57.3))^2), countyTable.countyName
1) I am SELECTing a column that contains the SQR function. I also have that column named as 'Distance'. However, when I try to ORDER BY on said column - and refer to it as 'Distance' - it asks for a value instead of sorting on that column. The only way I can get the query to ORDER BY is to duplicate the expression from the SELECT line. This seems unnecessary.
2) Right now, I have some values hard-coded in. I could care less about the values '57.3' and '69.1' However, for '46.47' I would like to replace with 'x2' and -90.17 with 'y2'. How I've been trying to write this with parameters, Access asks for values for each instance of 'x2' and 'y2'. This doesn't help me at all, so I have them hardcoded in.
Any help at all? Thanks!
1) I am SELECTing a column that contains the SQR function. I also have that column named as 'Distance'. However, when I try to ORDER BY on said column - and refer to it as 'Distance' - it asks for a value instead of sorting on that column. The only way I can get the query to ORDER BY is to duplicate the expression from the SELECT line. This seems unnecessary.
Yes Access does a poor job. Every real DBMS now supports ordering by the column alias created in the SELECT clause. To do this in Access, you can either do what you are doing (repeat the expression) or subquery it, e.g.
select a,b,c
from (
select a, b, a+b as C
from sometable
) AS SUBQUERIED
order by c
2) How I've been trying to write this with parameters, Access asks for values for each instance of 'x2' and 'y2'.
You're doing it wrong. Access should prompt only once. If you have a query like this
select a, b, a+b as C
from sometable
where a > [x] and y > [x]
It will see both [x]'s as being the same - and only one prompt for both. Just make sure they are spelt exactly the same.
If you wanted something like this simplified example:
SELECT
countyTable.countyName,
Sqr((69.1*(46.47-avgLatitude))^2+(69.1*(-90.17-avgLongitude)*Cos(avgLatitude/57.3))^2) as Distance
FROM countyTable
ORDER BY Distance;
For the ORDER BY you can reference that complex Distance expression by its ordinal position in the field list.
SELECT
countyTable.countyName,
Sqr((69.1*(46.47-avgLatitude))^2+(69.1*(-90.17-avgLongitude)*Cos(avgLatitude/57.3))^2) as Distance
FROM countyTable
ORDER BY 2;
That method is supported at least since Jet 4 (Access 2000), and also by the newer ACE database engine.

SQL statement HAVING MAX(some+thing)=some+thing

I'm having trouble with Microsoft Access 2003, it's complaining about this statement:
select cardnr
from change
where year(date)<2009
group by cardnr
having max(time+date) = (time+date) and cardto='VIP'
What I want to do is, for every distinct cardnr in the table change, to find the row with the latest (time+date) that is before year 2009, and then just select the rows with cardto='VIP'.
This validator says it's OK, Access says it's not OK.
This is the message I get: "you tried to execute a query that does not include the specified expression 'max(time+date)=time+date and cardto='VIP' and cardnr=' as part of an aggregate function."
Could someone please explain what I'm doing wrong and the right way to do it? Thanks
Note: The field and table names are translated and do not collide with any reserved words, I have no trouble with the names.
Try to think of it like this - HAVING is applied after the aggregation is done.
Therefore it can not compare to unaggregated expressions (neither for time+date, nor for cardto).
However, to get the last (principle is the same for getting rows related to other aggregated functions as weel) time and date you can do something like:
SELECT cardnr
FROM change main
WHERE time+date IN (SELECT MAX(time+date)
FROM change sub
WHERE sub.cardnr = main.cardnr AND
year(date)<2009
AND cardto='VIP')
(assuming that date part on your time field is the same for all the records; having two fields for date/time is not in your best interest and also using reserved words for field names can backfire in certain cases)
It works because the subquery is filtered only on the records that you are interested in from the outer query.
Applying the same year(date)<200 and cardto='VIP' to the outer query can improve performance further.