SQL Cast, Case and Count function - sql

I am trying to count rows of email opens and divide it by the total email sends and convert this into decimal (so it shows percentage).
I am getting the error: "An error occurred while checking the query syntax. Errors: Incorrect syntax near ')'."
I have tried separating the code so I can get the count and case function separately to cast. Cast works without the count/case. Count/case also works independently, it just doesn't seem to work all together. Am I missing something here?
SELECT
SubscriberKey
,CAST(
((COUNT(CASE
WHEN PreviousMonth <= 1
AND SendType = 'Auto'
AND Opened = 1
THEN 1
ELSE NULLEND ))/
(COUNT(CASE
WHEN PreviousMonth <= 1
AND SendType = 'Auto')))
AS DECIMAL(18,4)) * 100 AS 'AverageOpen'
FROM Data
GROUP BY SubscriberKey
An error occurred while checking the query syntax. Errors: Incorrect syntax near ')'.

I would write this using SUM(CASE). Note two things:
The 1.0 so the division is not integers (which can be an issue in some databases.
No else in the denominator to avoid divide-by-zero
I also left out the cast():
SELECT SubscriberKey
(SUM(CASE WHEN PreviousMonth <= 1 AND
SendType = 'Auto'
Opened = 1
THEN 1.0 ELSE 0
END) /
SUM(CASE WHEN PreviousMonth <= 1 AND
SendType = 'Auto'
THEN 1 -- no else so no divide by 0
END)
) * 100 AverageOpen
FROM Data
GROUP BY SubscriberKey;
You code may be failing because of NULLEND is not recognized in SQL.

I think what you want to achieve here is to get the average of opened = 1 divided by all.
SELECT cast((t1.Opened/t1.OverAll) as decimal(18,4)) * 100.00 as 'AverageOpen'
FROM
(SELECT
SubscriberKey
, SUM(CASE WHEN PreviousMonth <= 1 AND SendType = 'Auto' AND Opened = 1 THEN 1 ELSE 0 END) Opened,
, SUM(CASE WHEN PreviousMonth <= 1 AND SendType = 'Auto' THEN 1 ELSE 0 END) OverAll
FROM Data
GROUP BY SubscriberKey) as t1

Related

PostgreSQL WHERE cause to filter out results with 0 causes a syntax error

I'm trying to produce a SQL query where I have my IDs on the first column, then sum of page hits of accounts in column 2 and page hits of payments in column 3. The below code works, except for one point. I want to exclude any rows which have 0 in accounts column. When I add in the WHERE clause
SELECT
EVAR3 AS MYID
sum(case when web.Page.name = 'Accounts:Overview' then 1 else 0 end) as accounts
sum(case when web.Page.name = 'Payment:Overview' then 1 else 0 end) as payments
FROM mytable
WHERE
timestamp >= to_timestamp('2021-09-01') AND timestamp <= to_timestamp('2021-09-02')
AND
(sum(case when web.Page.name = 'Accounts:Overview' then 1 else 0 end) > 0)
GROUP BY EVAR3
ORDER BY EVAR3 ASC
This gives me an invalid expression error on my where clause saying generate expressions are not valid in the where clause. When I change WHERE to HAVING I get a syntax error saying it expected EOF rather than GROUP.
How do I correctly implement a filter to remove results with 0 in accounts to otherwise working code?
Since it is an aggregate function it should be HAVING but it should appear after the GROUP BY. the structure is SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY
SELECT
EVAR3 AS MYID,
sum(case when web.Page.name = 'Accounts:Overview' then 1 else 0 end) as accounts,
sum(case when web.Page.name = 'Payment:Overview' then 1 else 0 end) as payments
FROM mytable
WHERE
timestamp >= to_timestamp('2021-09-01') AND timestamp <= to_timestamp('2021-09-02')
GROUP BY EVAR3
HAVING (sum(case when web.Page.name = 'Accounts:Overview' then 1 else 0 end) > 0)
ORDER BY EVAR3 ASC

SQL using SUM in CASE in SUM

I had this query select
sum(CASE WHEN kpi.average >= temp.average THEN 1 ELSE 0 END) AS recordOrder,
which worked fine, but I had to change it to this
sum(CASE WHEN sum(kpi.averageUse) / sum(kpi.averageTotal) >= temp.average THEN 1 ELSE 0 END) AS recordOrder,
These queries have to get number of rows, where some value (average) is greater than average from TEMP table. But in the second query I have more accurate data (weighted average).
but I am getting error
1111 invalid use of group function
Any ideas how to write SUM in CASE in SUM?
Thanks!
This code is just non-sensical because you have nested sum functions:
sum(CASE WHEN sum(kpi.averageUse) / sum(kpi.averageTotal) >= temp.average THEN 1 ELSE 0 END) AS recordOrder,
Without seeing your larger query, it is not possible to know what you really intend. But I would speculate that you don't want the internal sum()s:
sum(CASE WHEN (skpi.averageUse / kpi.averageTotal) >= temp.average THEN 1 ELSE 0 END) AS recordOrder,

Syntax to resolve ORACLE error is ORA-01476: divisor is equal to zero

I'm using the NVL function to try and correct
ERROR: Error fetching from cursor. ORACLE error is ORA-01476: divisor is equal to zero.
I'm having trouble figuring out what the correct syntax is.
(nvl(sum(case when t.LABEL in (12,14,24,25,26,33) and t.sales_credit=1 then t.AMOUNT else 0 end),0) / nvl(sum(case when t.sales_credit=1 then t.AMOUNT else 0 end),0))*100 as DOLSHAR_COR_M
The normal method is nullif() in the dividend. So, instead of:
nvl(sum(case when t.sales_credit=1 then t.AMOUNT else 0 end), 0))
You would use:
nullif(sum(case when t.sales_credit=1 then t.AMOUNT else 0 end), 0))
Assuming that t.Amount is never negative or 0, it is sufficient to just drop the else 0:
sum(case when t.sales_credit = 1 then t.AMOUNT end)
There is nothing wrong with your query or syntax. Just change the logic of replacing null with 0.
The divisor can not be 0. so you need to use 1 instead, as follows:
SELECT
( NVL(SUM(CASE
WHEN T.LABEL IN(
12, 14, 24, 25, 26, 33
)
AND T.SALES_CREDIT = 1 THEN T.AMOUNT
ELSE 0
END), 0) /
NVL(SUM(CASE
WHEN T.SALES_CREDIT = 1 THEN T.AMOUNT
ELSE 0
END), 1 /*0*/) ) * 100 AS DOLSHAR_COR_M -- change here to avoid /0 error -- used 1 instead of 0
from DUAL;
I think it has no records for which SUM executes and making the whole expression as null.
Cheers!!

SQL - How to get the percentage of 2 sums

I am trying to get the CTR from uploads to clicks. How would I be able to get this percentage?
I am currently using the code below and I receive 0 as a result (view attached img).
SELECT geo_country, [created_at:date:aggregation] AS day,
SUM(case when name = 'adclick' then 1 else 0 end) as clicks,
SUM(case when name = 'camera_upload_image' then 1 else 0 end) as uploads,
CONVERT(DECIMAL(10,2), clicks / NULLIF(uploads, 0)) As CTR
FROM events
Results:
What you're running into is integer division.
If you take 2 integers
clicks = 3
uploads = 2
Then clicks / uploads equals 1 - not 1.5 as you expect:
http://sqlfiddle.com/#!18/0ed4a9/8/0
As you can see from that fiddle, the way around this is to ensure that your values are cast/converted to floating point numbers before doing the division.
Convert your results to decimal also:
SELECT geo_country, [created_at:date:aggregation] AS day,
SUM(case when name = 'adclick' then 1 else 0 end) as clicks,
SUM(case when name = 'camera_upload_image' then 1 else 0 end) as uploads,
CONVERT(DECIMAL(10,2), CONVERT(DECIMAL(10,2),clicks) / NULLIF(CONVERT(DECIMAL(10,2),uploads), 0)) As CTR
FROM events
Use a subquery or CTE:
SELECT c.*, clicks * 1.0 / NULLIF(uploads, 0) as ratio
FROM (SELECT geo_country, [created_at:date:aggregation] AS day,
SUM(case when name = 'adclick' then 1 else 0 end) as clicks,
SUM(case when name = 'camera_upload_image' then 1 else 0 end) as uploads
FROM events
GROUP BY geo_country, [created_at:date:aggregation]
) c;
The * 1.0 is to avoid integer division issues (i.e. 1/2=0 rather than 1.5. The NULLIF() is to avoid division by zero.

How to create a calculated field with a where clause in the calculation

The image shows the table from this code: select * from PunchClock
where punchmonth = 1 and PunchDay = 1 and PunchYear = 2018
I am trying to calculate the number of hours worked per day in a database. Our table for this has 2 columns that pertain to this. InOut is a column that has either 1 or 0 (1 = punch in, 0 = punch out), and then there is the punchdatetime. How could I use these two fields to calculate how many hours are worked per day.
I have tried to subtract the punch time in from the punch time out but that won't work.
select PunchMonth, PunchDay, PunchYear,
((PunchDateTime where InOut = 0) - (punchdatetime where InOut = 1))
from PunchClock
Error Message: Incorrect syntax near the keyword 'where'.
could be you need case (not where)
select PunchMonth
, PunchDay
, PunchYear
, case INOut = 0 then PunchDateTime else -PunchDateTime end
from PunchClock
I think you want a case expression. Also, because a given row has either an InOut value of 0 or 1 but not both, I think you need aggregation.
So, I'm guessing:
select PunchMonth, PunchDay, PunchYear,
datediff(second, min(case when InOut = 0 then punchdatetime end),
max(case when InOut = 1 then punchdatetime end)
) as seconds_diff
from PunchClock
group by PunchMonth, PunchDay, PunchYear;