I wrote the query below to calculate the death percentage in Postgresql and the result is zero,but same query in Bigquery gets the correct result. Can anyone have idea? Thanks!
SELECT
location,
MAX(total_cases) AS Cases_total,
MAX(total_deaths) AS Death_total, (MAX(total_deaths)/MAX(total_cases))*100 AS DeathPercentange
FROM covid_deaths
WHERE continent IS NOT NULL
GROUP BY location
ORDER BY DeathPercentange DESC;
I am not allowed to insert my screenshot so I have the link:
Same query in Bigquery
Query in PostgreSQL
The database looks like this:
The preview of the database
The result is ok, your operation is between big integers. The result is just an integer.
112/9766 = 0 * 100 = 0
If you want a numeric as result you have to cast your columns as numeric
SELECT
location,
MAX(total_cases) AS Cases_total,
MAX(total_deaths) AS Death_total, (MAX(total_deaths)::numeric/MAX(total_cases)::numeric)*100 AS DeathPercentange
FROM covid_deaths
WHERE continent IS NOT NULL
GROUP BY location
ORDER BY DeathPercentange DESC;
You do integer division. The result will always be 0 whenever total_deaths < total_cases (which is most likely your case). What you should do is cast to float or decimal at least one operand, e.g.
(MAX(total_deaths)::decimal / MAX(total_cases))*100 AS DeathPercentange
Related
I have two issues:
I am trying to create a pivot table using the crosstabs tablefunc but all of the queries I've tried are returning NULL for all values.
I have two grouping variables (airport code and date) that are in one row of data that need to be separate columns in the pivot table, but I can only seem to get one to work.
I have gotten the pivot table to partially work by ignoring the date value for the moment. When I leave 'yyyymm' out of my query, the setup of my output table is okay, but the values don't calculate properly.
The data: I have rows with various airport codes, aircraft user and engine codes, flight identifiers, and year/month values. Each row counts for one flight. A simplified example looks like this:
ident
primary_fa
user_engn
yyyymm
20191122-AFR-23
MKE
O_O
201911
20191210-ASH-61
N90
T_R
201912
20200120-EDV-2
MKE
C_J
202001
20200811-FLC-148
A90
O_O
202008
I need my output table to count the number of arrivals for each user engine combo grouped by airport code and yyyymm. So the rows would be each airport code (primary_fa), yyyymm and columns would be user_engn codes (O_O, T_R, C_J, etc.) with counts for the number of flights per user_engn.
My goal output would look something like this:
primary_fa
yyyymm
C_J
T_R
O_O
MKE
201911
1
0
1
N90
201912
0
1
0
A90
202008
0
0
1
But I am getting this (because I have to ignore the date portion to even get this far):
primary_fa
C_J
T_R
O_O
MKE
NULL
NULL
NULL
N90
NULL
NULL
NULL
A90
NULL
NULL
NULL
I've tried a lot of different versions of the crosstabs query and the closest I have gotten to correct is this:
SELECT *
FROM crosstab(
'SELECT primary_fa as locid,
yyyymm,
count(*)
FROM fy20_keeps_emdf
GROUP BY primary_fa, yyyymm
ORDER BY 1,2',
'VALUES (''C_J''),(''O_O''),(''T_R'')')
AS (primary_fa varchar,
C_J bigint,
O_O bigint,
T_R bigint);
Am I missing something obvious or do I need to do more data manipulation to get this to work?
I am trying to return sums with their specific conditions.
SELECT
COUNT(*),
SUM("transactionTotal" WHERE "entryType"=sold) as soldtotal,
SUM(case when "entryType"=new then "transactionTotal" else 0 end) as newtotal
FROM "MoneyTransactions"
WHERE cast("createdAt" as date) BETWEEN '2020-10-08' AND '2020-10-09'
I am trying to sum up the rows with "entryType"=sold and "entryType"=new and return those values separately.
obviously both my logic are wrong.
can someone lend a hand.
You were on the right track to use conditional aggregation, but your syntax is slightly off. Try this version:
SELECT
COUNT(*) AS total_cnt,
SUM(transactionTotal) FILTER (WHERE entryType = 'sold') AS soldtotal,
SUM(transactionTotal) FILTER (WHERE entryType = 'new') AS newtotal
FROM MoneyTransactions
WHERE
createdAt::date BETWEEN '2020-10-08' AND '2020-10-09';
Note: Assuming your createdAt column already be date, then there is no point in casting it. If it is text, then yes you would need to convert it, but you might have to use TO_DATE depending on its format.
SELECT * FROM table1 WHERE spent>= '1000'
This query still bring out numbers such as 598.99 and 230.909. My question is why is it doing this when I asked to search over or equal to 1000. Is there anyway to query so it only shows equal and more than 1000?
This happens because your '1000' is a text value. The other value is (or is converted to) text, too, so you end up with byte-per-byte comparison.
598.99 is greater then 1000 because 5... is greater then 1....
Cast to numeric types to do a proper comparison:
SELECT * FROM table1 WHERE spent::numeric >= '1000'::numeric
Or simply:
SELECT * FROM table1 WHERE spent::numeric >= 1000
You must compare numbers to get numeric comparison.
Use
WHERE CAST(spent AS numeric) >= 1000
This is my result set
i am returning this result set on the base of refid using WHERE refid IN.
Over here, i need to apply a logic without any kind of programming (means SQL query only).
if in result set, i am getting period for particular refid then other rows with the same refid must not returned.
for example, 2667105 having period then myid = 612084598 must not get returned in result set.
according to me this can be achieved using CASE but i have no idea how to use it, i mean that i don't know should i use the CASE statement in SELECT statement or WHERE clause...
EDIT:
This is how it suppose to work,
myid = 612084598 is the default row for refid = 2667105 but if specifically wants the refid for period = 6 then it must return all rows except myid = 612084598
but if i am looking for period = 12, for this period no specific refid present in database.. so for this it must return all rows except first one.. means all rows with the refid which is default one..
Not very clear definition of the problem, but try this:
with cte as (
select
*,
first_value(period) over(partition by refid order by myid) as fv
from test
)
select
myid, refid, period
from cte
where period is not null or fv is null
sql fiddle demo
Assuming the following query:
SELECT
ID,
COUNT(1) AS NumRecords,
SUM(Quantity) AS TotalQty
SUM(Quantity)/COUNT(1) AS Avg
FROM SOME_TABLE
GROUP BY ID
Right now it returns:
ID NumRecords TotalQty Avg
1 15 6 2
I want it to return a decimal value with a Scale of 2 for Avg (i.e. "2.5").
I've tried to CAST the calcluation as a DECIMAL, NUMERIC, FLOAT, and VARCHAR, but it always returns an INTEGER.
You need to cast the inputs to the calculation not the result. Also any reason you aren't using the AVG function?
AVG(CAST(Quantity as decimal(10,2)))
An alternative solution is via implicit Casting. I found this to be much cleaner SQL as well. The precision will be determined by the number of trailing zeros used when multiplying by 1.
AVG(Quantity * 1.00) //x.xx
AVG(Quantity * 1.0000) //x.xxxx