sql count query with case statement - sql

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.

Related

sql group by satisfying multiple conditions within the group

I have a table like below:
I want to select the group which has RELB_CD =9093 and INFO_SRC_CD with 7784. Both conditions should be present in the group. In the table below my output should be the group with id=139993690.
You can use aggregation with having:
select id
from t
group by id
having sum(case when relb_cd = 9093 then 1 else 0 end) > 0 and
sum(case when info_src_cde = 7784 then 1 else 0 end) > 0
hey use this code hope this will help you.
you have to ignore the date column because that one is not allowing to group
select id,fisc_ind, sum(sls_amt),relb_cd,info_scop,info_src_cd from yourtable group by id,fisc_ind,relb_cd,info_scop,info_src_cd
Another working answer. If your data are large, you could compare both GL's and this working answer and see which runs faster for you. I honestly don't know which is faster. This was slightly faster with a very short set of data.
select id
from table1
where relb_cd = 9093
intersect
select id
from table1
where info_src_cd = 7784

Oracle Query with two 'HAVING' conditions

I have a query and i want to have two HAVING conditions
The first condition is where sum is more than 6000 (Which i have
done)
The second condition is where the COUNT(1) CNT is more than 1 (Which
i need help in)
SELECT SYSDATE,
CUSTOMER.CIF_NO,
CUSTOMER.LONG_NAME_ENG,
TRANSTYPE.short_desc_Eng,
LOCATION.LONG_DESC_ENG ,
COUNT(1) CNT,
SUM(TRANS.AMOUNT) SM
FROM TRANS, CUSTOMER, TRANSTYPE, LOCATION
WHERE TRANS.TRS_AC_CIF = CUSTOMER.CIF_NO
AND TRANS.BRANCH_CODE = LOCATION.BRANCH_CODE
AND TRANS.COMP_CODE = LOCATION.COMP_CODE
AND TRANSTYPE.COMP_CODE = TRANS.COMP_CODE
AND TRANSTYPE.TYPE IN ( 'D' , 'T' )
AND TRANSTYPE.CODE = TRANS.TRX_TYPE
AND TRANS.STATUS = 'P'
AND TRANS.TRS_TYPE = 'R'
AND TRANS.CB_IND = 'C'
GROUP BY CUSTOMER.CIF_NO ,CUSTOMER.LONG_NAME_ENG,
TRANSTYPE.short_desc_Eng, LOCATION.LONG_DESC_ENG
HAVING SUM(TRANS.AMOUNT) > 6000
---------------------------
second having here
----------------------------
ORDER BY CUSTOMER.CIF_NO, CUSTOMER.LONG_NAME_ENG, LOCATION.LONG_DESC_ENG
More than one HAVING clause can not be specified within a SELECT statement, e.g. it's a violation. But add your needed condition such as
HAVING SUM(TRANS.AMOUNT) > 6000 AND COUNT(1) > 1
OR
HAVING SUM(TRANS.AMOUNT) > 6000 OR COUNT(1) > 1
as long as
a GROUP BY clause is present with the SQL statement
aggregations take place within the HAVING clause
P.S. Convert your query syntax to the syntax with explicit JOIN clauses among tables rather than old-style comma-seperated JOINs, and use aliases for the table names

Partition table based on joined table

We have 2 Tables Lead and Task.
One lead can have multiple Tasks.
We want to determine if a Lead has a Task who's description contains String 'x'.
If the Lead has the String the it should belong to group1 if it doesn't to group2.
Then we want to count the leads per group and week.
The problem we have is that if a Lead has several tasks and one of them has string 'x' in its description and the others don't it is counted in both groups.
We would need something that resembles a break; statement in the IFF clause of the subquery, so that if the first condition = Contain string x is satisfied the other tasks are not counted anymore.
How would we achieve that?
So far we have the following statement:
--SQL:
SELECT LeadDate, GROUP, COUNT(LEAD_ID_T1)
FROM LEAD Lead INNER JOIN
(SELECT DISTINCT LEAD.ID AS LEAD_ID_T1,
IFF(CONTAINS(Task.DESCRIPTION,
'x'),
'GROUP1',
'GROUP2') AS GROUP
FROM TASK Task
RIGHT JOIN LEAD ON TASK.WHO_ID = LEAD.ID
) T1 ON T1.LEAD_ID_T1 = LEAD.ID
GROUP BY LeadDate,GROUP;
Code breaks because it can not aggregate the measures.
Really thankful for any input. This has been bothering me for a few days now.
I am thinking EXISTS with a CASE expression:
select l.*,
(case when exists (select 1
from task t
where t.who_id = l.id and
t.description like '%x%'
)
then 'GROUP1' else 'GROUP2'
end) as the_group
from lead l;
You can also try something like this, CASE with 1 and 0 then take the SUM
SELECT LeadDate,
sum(CASE When t.description like '%x%'then 1 else 0 end) as Group1,
sum(CASE When t.description like '%x%'then 0 else 1 end) as Group2
FROM TASK t
RIGHT JOIN LEAD l ON t.WHO_ID = l.ID
GROUP BY LeadDate;

SQL Select COUNT(Value=Value) Possible?

I want to Count all the rows that only have the value I want like this:
SELECT Users.Balance,
Users.FreeBids,
COUNT(Bids.Burned = 0) AS 'ActiveBids',
COUNT(Bids.Burned = 1) AS 'BurnedBids'
FROM Users
INNER JOIN Bids
ON Users.ID = Bids.BidderID
WHERE Users.ID = 2
GROUP BY Users.Balance,
Users.FreeBids
It says "Invalid Syntax Neat '=' It works perfectly without the '='.
How can I count the rows that Burned=1 in them and Burned=0 in them?
Thanks,
Dan
Use a CASE statement
COUNT(CASE WHEN Bids.Burned=0 THEN 1 END) AS 'ActiveBids',
COUNT(CASE WHEN Bids.Burned=1 THEN 1 END) AS 'BurnedBids'
There is an implicit ELSE NULL. COUNT only counts NOT NULL values so this will give you the result you need.

Most optimized way to get column totals in SQL Server 2005+

I am creating some reports for an application to be used by various states. The database has the potential to be very large. I would like to know which way is the best way to get column totals.
Currently I have SQL similar to the following:
SELECT count(case when prg.prefix_id = 1 then iss.id end) +
count(case when prg.prefix_id = 2 then iss.id end) as total,
count(case when prg.prefix_id = 1 then iss.id end) as c1,
count(case when prg.prefix_id = 2 then iss.id end) as c2
FROM dbo.TableName
WHERE ...
As you can see, the columns are in there twice. In one instance, im adding them and showing the total, in the other im just showing the individual values which is required for the report.
This is a very small sample of the SQL, there are 20+ columns and w/i those columns 4 or more of them are being summed at times.
I was thinking of declaring some #Parameters and setting each of the columns equal to a #Parameter, then I could just add up which ever #Parameters I needed to show the column totals, IE: SET #Total = #c1 + #c2
But, does the SQL Server engine even care the columns are in there multiple times like that? Is there a better way of doing this?
Any reason this isn't done as
select prg.prefix_id, count(1) from tablename where... group by prg.prefix_id
It would leave you with a result set of the prefix_id and the count of rows for each prefix_ID...might be preferential over a series of count(case) statements, and I think it should be quicker, but I can't confirm for sure.
I would use a subquery before resorting to #vars myself. Something like this:
select c1,c2,c1+c1 as total from
(SELECT
count(case when prg.prefix_id = 1 then iss.id end) as c1,
count(case when prg.prefix_id = 2 then iss.id end) as c2
FROM dbo.TableName
WHERE ... ) a
Use straight SQL if you can before resorting to T-SQL procedure logic. Rule of thumb if you can do it in SQL do it in SQL. If you want to emulate static values with straight SQL try a inline view like this:
SELECT iv1.c1 + iv1.c2 as total,
iv1.c1,
iv1.c2
FROM
(
SELECT count(case when prg.prefix_id = 1 then iss.id end) as c1,
count(case when prg.prefix_id = 2 then iss.id end) as c2
FROM dbo.TableName
WHERE ...
) AS iv1
This way you logically are getting the counts once and can compute values based on those counts. However I think SQL Server is smart enough to not have to scan for the count n number of times so I don't know that your plan would differ from the SQL I sent and the SQL you have.