Syntax of nested sql aggregate functions - sql

I'm learning SQL on codecademy
There's an example of nested aggregate function:
SELECT ROUND(AVG(price), 2)
FROM fake_apps;
ROUND() requires a number as first parameter, how can AVG(price) be plugged in here? What's the datatype of it?
If I change the code to:
SELECT ROUND(SELECT AVG(price)
FROM fake_apps, 2)
FROM fake_apps;
The code throws a syntax error.

The below code gives a syntax error because ROUND is a scalar function. It expects exactly one value as the first parameter.
SELECT ROUND(SELECT AVG(price)
FROM fake_apps, 2)
FROM fake_apps;
SELECT AVG(price) FROM fake_apps returns a set of rows.
On the other hand, AVG is an aggregate function. It operates on a set of rows. The return type is numeric.

I don't think it needs nested select query, at least as per your requirement example you have provided. This may be resolved with following query also.
SELECT ROUND( AVG (price), 2 ) FROM fake_apps
DataType should be decimal or numeric with precision (for e.g. numeric (18,3) )
Let me know if I interpreted as wrong question and correct me, so I can try another way.

Related

Calculating percentage in sql not working properly

I have the following code:
select country_of birth, count(*)/(select count(*) from person)*100
from person
group by country_of_birth;
However, it's not getting the correct result.
You are experiencing the down sides of integer division.
In PostgreSQL, the result of the division of two integers is again an integer (the truncated result).
So 7 / 3 = 2 in PostgresSQL.
If you want an exact result, cast to numeric:
CAST (7 AS numeric) / CAST (3 AS numeric)
You can omit one of the casts, because PostgreSQL will automatically cast to the more generic numeric data type if the types of the arguments are different.
I doubt this will fix the problem of incorrect results, but I would encourage you to use window functions:
select country_of_birth,
count(*) * 100.0 / sum(count(*)) over () as percentage
from person
group by country_of_birth;

Change type of calculated field in select query (sqlite)

im sure i am not the first one to ask this but i can't find the answer to this:
I haver a select query on a datatable in a sqlite database.
select *, ((int_EndTime)-(int_StartTime))/60 as dou_usage_min FROM tbl_unautho_usage;
when i run this i get all the fields from the datatable including a new column calculated from to integer columns with unix time stamp values. However, i want my calculated column to be of the type double. With the query above i get a type integer.
select *, ((int_EndTime as float)-(int_StartTime as float))/60 as dou_usage_min FROM tbl_unautho_usage;
Afterwards I tried to change the column type of my integer-columns to float, but this gies me the following error:
near "as": syntax error:
i got the idea for that from the following post:
How to cast computed column with correct decimal/$ result
Try multiplying a value used within the arithmetic operation by 1.0.
select
*,
((int_EndTime*1.0)-(int_StartTime*1.0))/60 as dou_usage_min
FROM tbl_unautho_usage;
Probably only one value multiplied will be sufficient.
The correct syntax of a CAST expression is "CAST(something AS type)".
But in this case, for the division to be done with floating-point numbers, it is sufficient for at least one of the operands to be a floating-point number:
SELECT *, (int_EndTime - int_StartTime) / 60.0 ...

Cannot use calculated offset in BigQuery's DATE_ADD function

I'm trying to create a custom query in Tableau to use on Google's BigQuery. The goal is to have an offset parameter in Tableau that changes the offsets used in a date based WHERE clause.
In Tableau it would look like this:
SELECT
DATE_ADD(UTC_USEC_TO_MONTH(CURRENT_DATE()),<Parameters.Offset>-1,"MONTH") as month_index,
COUNT(DISTINCT user_id, 1000000) as distinct_count
FROM
[Orders]
WHERE
order_date >= DATE_ADD(UTC_USEC_TO_MONTH(CURRENT_DATE()),<Parameters.Offset>-12,"MONTH")
AND
order_date < DATE_ADD(UTC_USEC_TO_MONTH(CURRENT_DATE()),<Parameters.Offset>-1,"MONTH")
However, BigQuery always returns an error:
Error: DATE_ADD 2nd argument must have INT32 type.
When I try the same query in the BigQuery editor using simple arithmetic it fails with the same error.
SELECT
DATE_ADD(UTC_USEC_TO_MONTH(CURRENT_DATE()),5-3,"MONTH") as month_index,
FROM [Orders]
Any workaround for this? My only option so far is to make multiple offsets in Tableau, it seems.
Thanks for the help!
I acknowledge that this is a hole in functionality of DATE_ADD. It can be fixed, but it will take some time until fix is rolled into production.
Here is a possible workaround. It seems to work if the first argument to DATE_ADD is a string. Then you can truncate the result to a month boundary and convert it from a timestamp to a string.
SELECT
FORMAT_UTC_USEC(UTC_USEC_TO_MONTH(DATE_ADD(CURRENT_DATE(),5-3,"MONTH"))) as month_index;

Select data in date format

I have a query in which I want to select data from a column where the data is a date. The problem is that the data is a mix of text and dates.
This bit of SQL only returns the longest text field:
SELECT MAX(field_value)
Where the date does occur, it is always in the format xx/xx/xxxx
I'm trying to select the most recent date.
I'm using MS SQL.
Can anyone help?
Try this using ISDATE and CONVERT:
SELECT MAX(CONVERT(DateTime, MaybeDate))
FROM (
SELECT MaybeDate
FROM MyTable
WHERE ISDATE(MaybeDate) = 1) T
You could also use MAX(CAST(MaybeDate AS DateTime)). I got in the (maybe bad?) habit of using CONVERT years ago and have stuck with it.
To do this without a conversion error:
select max(case when isdate(col) = 1 then cast(col as date) end) -- or use convert()
from . . .
The SQL statement does not specify the order of operations. So, even including a where clause in a subquery will not guarantee that only dates get converted. In fact, the SQL Server optimizer is "smart" enough to do the conversion when the data is brought in and then do the filtering afterwards.
The only operation that guarantees sequencing of operations is the case statement, and there are even exceptions to that.
Another solution would be using PATINDEX in WHERE clause.
SELECT PATINDEX('[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9]', field_value)
Problem with this approach is you really are not sure if something is date (e.g. 99/99/9999 is not date).
And problem with IS_DATE is it depends on configuration (e.g. DATEFORMAT).
So, use an appropriate option.

How to get around "convert varchar to float" error

I have a table that has non-numeric values in the source.
I am using a CTE to filter down to a set of values that is all numeric.
However, when I try to convert the filtered list to float, I get an error.
Goal is to find all Lab Results that are less than 8.0
CTE:
;with labs AS (
SELECT LabResult_Result
FROM VIEW_PatientLabResult
WHERE (LabResult_DateTimeOfObservation between '1/1/2012' and '1/1/2013') and
MasterLabCode_Description='Hemoglobin (Hgb) A1c'
)
Results in ~250 rows, all of which are decimal (manually checked).
Cannot get to convert them to float for comparison. Best I have so far is:
select * from
(
select *, CAST( labresult_result as float) as Converted
FROM labs
) Conv
WHERE Conv.Converted < 8.0
This results in Error converting data type varchar to float.
Without the WHERE clause, the query runs fine.
I am thinking that SQL is trying to convert the entire results before the CTE filter. Is there a way to make it run in order?
SQL only guarantees the order of execution when you use a case statement. (Although as Aaron points out, this is not true for aggregated values in a group by expression.)
Try this instead:
select *
from (select *, (case when ISNUMERIC(labresult_result) = 1 then CAST(labresult_result as float)
end) as Converted
FROM labs
) conv
where conv.converted < 8.0
In the original query, SQL is free to rearrange the where clauses to optimize the query -- even between CTEs and subqueries. This can result in an unexpected error. Remember, SQL is a descriptive language that describes the output, not a procedural language that specifies how things are processed.