I am writing a SQL statement against an Oracle 10g database. I want to obtain the SUM of a field with three different conditions. Can I do this with one query?
This is pseudo-SQL for what I want:
SELECT SUM(CP) AS CPTotal,
(SUM(CP) FROM tasks WHERE Code='P') AS CPProd,
(SUM(CP) FROM tasks WHERE Code='S') AS CPSupp
FROM tasks;
A conditional SUM() can be had via CASE statements:
SELECT SUM(CP) AS CPTotal,
SUM(CASE WHEN Code = 'P' THEN CP ELSE 0 END) AS CPProd,
SUM(CASE WHEN Code = 'S' THEN CP ELSE 0 END) AS CPSupp
FROM tasks;
The ELSE portion is not needed as NULL results when a value does not match any criteria in a CASE statement, and NULL is ignored on aggregation, but some prefer to include it.
You can use CASE to conditional check for the value of code.
SELECT SUM(CP) AS CPTotal,
SUM(CASE WHEN Code = 'P' THEN CP END) AS CPProd,
SUM(CASE WHEN Code = 'S' THEN CP END) AS CPSupp
FROM tasks
Related
I have an access to Oracle server. There is a table on the Oracle server called Transactions which contains the following data:
I don't known the number of values, so we need to implement dynamic sql in Oracle.
I need to pivot that data so the results are:
Any suggestions?
You can use conditional aggregation:
select subno,
sum(case when offer = 'offer1' then 1 else 0 end) as offer1,
sum(case when offer = 'offer2' then 1 else 0 end) as offer2,
sum(case when offer = 'offer3' then 1 else 0 end) as offer3
from t
group by subno;
I have a table which consists of data where in I'm having trouble counting the corresponding rows.
Here is the sample table:
I am expecting an output like this:
You can do conditional aggregation:
select
sum(case when result = 'X' then 1 else 0 end) count_x,
sum(case when result is null then 1 else 0 end) count_blank
from mytable
I assume that by blank you mean null. If not, then you can change the condition in the second sum() from result is null to result = ''.
If you are running MySQL, this can be shortened a little:
select
sum(result = 'X') count_x,
sum(result is null) count_blank
from mytable
I have a line of SQL which produces a count of purchases variable
count(distinct case when t.transaction_sub_type =1 then t.transaction_date end) as COUNTPUR,
I need to modify this so I can produce a 0/1 flag variable, which flags if a customer is a repeat purchaser. So, when a customer's purchases are greater than 1 then flag as 1 else flag as 0.
case when COUNTPUR>1 then 1 else 0 end as FLAG_REPEATPURCHASER
I need to combine these two case statements into one. I have been experimenting with different versions of the syntax, but I can't seem to nail it down. Below is one of the experiments which do not work.
max(case when (count(distinct case when t.transaction_sub_type =1 then t.transaction_date end))>1 then 1 else 0 end) as FLAG_REPEATPURCHASER,
Thanks in advance for assitance
You can use a case expression with conditional aggregation:
(case when count(distinct case when t.transaction_sub_type = 1 then t.transaction_date end) > 1
then 1 else 0
end) as FLAG_REPEATPURCHASER
I have to execute a query from three tables avg_salary, person and emails. This simple sql query works fine.
SELECT avg_salary.id, COUNT(emails.message_from) AS email_PGA
FROM avg_salary, person, emails
WHERE person.works_in = avg_salary.id
AND person.email_address = emails.message_from
AND person.salary::numeric > avg_salary.avg
GROUP BY avg_salary.id
But I want to add another column email_PLA with the condition when
person.salary::numeric < avg_salary.avg. I can do that by joining the whole query again. But I want to use CASE in this situation. And even after trying so many times I can't get the syntax right.
I assume you need another count?
You would need something like:
SUM(CASE WHEN (person.salary::numeric < avg_salary.avg) THEN 1 ELSE 0 END) AS email_PGA
You can do conditional aggregation by using case expression and always use explicit JOIN syntax
SELECT avg_salary.id,
SUM(CASE WHEN p.salary::numeric > asal.avg THEN 1 ELSE 0 END) AS email_PGA,
SUM(CASE WHEN p.salary::numeric < asal.avg THEN 1 ELSE 0 END) AS email_PLA
FROM avg_salary asal,
INNER JOIN person p on p.works_in = asal.id
INNER JOIN emails e on e.message_from = p.email_address
--WHERE p.salary::numeric > asal.avg
GROUP BY avg_salary.id;
If you need different columns on specific conditions you have to do different SQL queries.
I am not entirely sure if this is possible in SQL (I am by no means an expert).
I have lines of data in TABLEA like below:
I wish to have an SQL output that will 'group' any records together that where Activity!=D. The output results would need look like the table below:
Any 'merged' activities would would be grouped as 'Merged'. In the example, this would be A and B.
I got started
select
cycle_start,
cycle_end,
activity_start,
activity_end,
case when (Activity="D") then "D" else "Merged" end
but then I struggle to get the aggregation correct
Yes, you can do this with a case in the group by:
select cycle_start, cycle_end,
min(activity_start) as activity_start,
max(activity_end) as activity_end,
(case when Activity = 'D' then 'D' else 'Merged' end)
from table t
group by cycle_start, cycle_end,
(case when Activity = 'D' then 'D' else 'Merged' end)