using sql count in a case statement - sql

I have a table and i need to present the output in the following fashion.
tb_a:
col1 | reg_id | rsp_ind
Count of rows with rsp_ind = 0 as 'New' and 1 as 'Accepted'
The output should be
NEW | Accepted
9 | 10
I tried using the following query.
select
case when rsp_ind = 0 then count(reg_id)end as 'New',
case when rsp_ind = 1 then count(reg_id)end as 'Accepted'
from tb_a
and i m getting output as
NEW | Accepted
NULL| 10
9 | NULL
Could someone help to me tweak the query to achieve the output.
Note : I cannot add a sum surrounding this. Its part of a bigger program and so i cannot add a super-query to this.

SELECT
COUNT(CASE WHEN rsp_ind = 0 then 1 ELSE NULL END) as "New",
COUNT(CASE WHEN rsp_ind = 1 then 1 ELSE NULL END) as "Accepted"
from tb_a
You can see the output for this request HERE

Depending on you flavor of SQL, you can also imply the else statement in your aggregate counts.
For example, here's a simple table Grades:
| Letters |
|---------|
| A |
| A |
| B |
| C |
We can test out each Aggregate counter syntax like this (Interactive Demo in SQL Fiddle):
SELECT
COUNT(CASE WHEN Letter = 'A' THEN 1 END) AS [Count - End],
COUNT(CASE WHEN Letter = 'A' THEN 1 ELSE NULL END) AS [Count - Else Null],
COUNT(CASE WHEN Letter = 'A' THEN 1 ELSE 0 END) AS [Count - Else Zero],
SUM(CASE WHEN Letter = 'A' THEN 1 END) AS [Sum - End],
SUM(CASE WHEN Letter = 'A' THEN 1 ELSE NULL END) AS [Sum - Else Null],
SUM(CASE WHEN Letter = 'A' THEN 1 ELSE 0 END) AS [Sum - Else Zero]
FROM Grades
And here are the results (unpivoted for readability):
| Description | Counts |
|-------------------|--------|
| Count - End | 2 |
| Count - Else Null | 2 |
| Count - Else Zero | 4 | *Note: Will include count of zero values
| Sum - End | 2 |
| Sum - Else Null | 2 |
| Sum - Else Zero | 2 |
Which lines up with the docs for Aggregate Functions in SQL
Docs for COUNT:
COUNT(*) - returns the number of items in a group. This includes NULL values and duplicates.
COUNT(ALL expression) - evaluates expression for each row in a group, and returns the number of nonnull values.
COUNT(DISTINCT expression) - evaluates expression for each row in a group, and returns the number of unique, nonnull values.
Docs for SUM:
ALL - Applies the aggregate function to all values. ALL is the default.
DISTINCT - Specifies that SUM return the sum of unique values.

Close... try:
select
Sum(case when rsp_ind = 0 then 1 Else 0 End) as 'New',
Sum(case when rsp_ind = 1 then 1 else 0 end) as 'Accepted'
from tb_a

The reason you're getting two rows instead of one is that you are grouping by rsp_ind in the outer query (which you did not, to my disappointment, share with us). There is nothing you can do to force one row instead of two without dealing with that GROUP BY item.

CREATE TABLE #CountMe (Col1 char(1));
INSERT INTO #CountMe VALUES ('A');
INSERT INTO #CountMe VALUES ('B');
INSERT INTO #CountMe VALUES ('A');
INSERT INTO #CountMe VALUES ('B');
SELECT
COUNT(CASE WHEN Col1 = 'A' THEN 1 END) AS CountWithoutElse,
COUNT(CASE WHEN Col1 = 'A' THEN 1 ELSE NULL END) AS CountWithElseNull,
COUNT(CASE WHEN Col1 = 'A' THEN 1 ELSE 0 END) AS CountWithElseZero
FROM #CountMe;

If you want to group the results based on a column and take the count based on the same, you can run the query as :
$sql = "SELECT COLUMNNAME,
COUNT(CASE WHEN COLUMNNAME IN ('YOURCONDITION') then 1 ELSE NULL END) as 'New',
COUNT(CASE WHEN COLUMNNAME IN ('YOURCONDITION') then 1 ELSE NULL END) as 'ACCPTED'
FROM TABLENAME
GROUP BY COLUMNANME";

select sum(rsp_ind = 0) as `New`,
sum(rsp_ind = 1) as `Accepted`
from tb_a

ok. I solved it
SELECT `smart_projects`.project_id, `smart_projects`.business_id, `smart_projects`.title,
`page_pages`.`funnel_id` as `funnel_id`, count(distinct(page_pages.page_id) )as page_count, count(distinct (CASE WHEN page_pages.funnel_id != 0 then page_pages.funnel_id ELSE NULL END ) ) as funnel_count
FROM `smart_projects`
LEFT JOIN `page_pages` ON `smart_projects`.`project_id` = `page_pages`.`project_id`
WHERE smart_projects.status != 0
AND `smart_projects`.`business_id` = 'cd9412774edb11e9'
GROUP BY `smart_projects`.`project_id`
ORDER BY `title` DESC

Related

Calculate difference in Oracle table from sum

I have a table which looks as followed:
ID | Value
A | 2
A | 5
A | 6
B | 1
B | 7
B | -3
I am currently using a statement as followed
select ID, sum(VALUE)
where ...
group by ID.
Now I need the difference from A and B.
Could anyone send me on the right path? I am working with Oracle.
Use conditional aggregation:
SELECT SUM(CASE WHEN id = 'A' THEN "Value" ELSE 0 END) -
SUM(CASE WHEN id = 'B' THEN "Value" ELSE 0 END) "Difference"
FROM tablename;
See the demo.

BigQuery : case when expression to Count from Same column but different conditions

I have a table with 2 columns as below:
Col 1 | col_stats
Field 1 | open
Field 2 | close
Field 1 | close
Field 1 | open
I want the ouput to be as :
Col1 | cnt_open | Cnt_close
Field 1 | 2 | 1
Field 2 | 0 | 1
**I wrote a query **
select col 1, count(case when col_stats= 'open' then 1 else 0 END) cnt_open,
count (case when col_stats= 'close' then 1 else 0 END ) cnt_close
from `project.dataset.tablename`
group by col1
Resultant output from above query is incorrect:
Col1 | cnt_open | Cnt_close
Field 1 | 2 | 2
Field 2 | 1 | 1
Can somebody let me know why the output is giving incorrect result for count even after case condition is applied?
Use countif():
select col1, countif(col_stat = 'open') as num_opens, countif(col_stat = 'closed') as num_closes
from t
group by col1;
In SQL count() counts the number of non-NULL values. Your code would work with sum(). But countif() is simpler and clearer.
Use null instead of 0:
select col1, count(case when col_stats= 'open' then 1 else null END) cnt_open,
count (case when col_stats= 'close' then 1 else null END ) cnt_close
from `project.dataset.tablename`
group by col1

How to find Sum of positive values and negative values separately in a column

If there is a column number which has 5 rows as follows:
+----------+
| values |
+----------+
| -2 |
| -1 |
| 0 |
| 1 |
| 2 |
| 3 |
+----------+
I need the sum of all negative values and the sum of all positive values in my resultset.
The problem context is not clear. So, I'll assume this is about data stored in a RDBMS table. I'll also assume you want to use SQL language to get results.
suppose table is DATA_TABLE and column name which interests us isVALUE then, query should look like
SELECT
SUM(CASE WHEN VALUE > 0 THEN VALUE ELSE 0 END) POSITIVE_BALANCE,
SUM(CASE WHEN VALUE < 0 THEN VALUE ELSE 0 END) NEGATIVE_BALANCE
FROM DATA_TABLE;
If assumptions are incorrect, please edit your question with more details, context of the questions and programming environment where you want to solve it.
Using a CASE expression:
SELECT SUM(CASE WHEN col > 0 THEN col ELSE 0 END) AS posSum,
SUM(CASE WHEN col < 0 THEN col ELSE 0 END) AS negSum
FROM yourTable
I guess you'll need to combine tow queries in one like this:
SELECT (SELECT SUM(col) FROM my_table WHERE col > 0) as positive_val,
(SELECT SUM(col) FROM my_table WHERE col < 0) as negative_val
You can try something real simple like this:
SLEECT * FROM
(SELECT SUM (VALUE) POS_SUM FROM TABLE WHERE VALUE > 0) A
JOIN
(SELECT SUM (VALUE) NEG_SUM FROM TABLE WHERE VALUE < 0) B
ON 1 = 1;
Vijaykymar’s solution would also work.
SELECT SUM(values) FROM yourTable WHERE value <> 0 GROUP BY SIGN(values)
Edit:
SQL> SELECT * FROM NUMBER_DATA WHERE value <> 0;
VALUE
----------
2
-3
4
5
-9
1
5
7
-8
10
SQL> SELECT SIGN(VALUE), SUM(VALUE) FROM NUMBER_DATA WHERE value <> 0 GROUP BY SIGN(VALUE);
SIGN(VALUE) SUM(VALUE)
----------- ----------
1 34
-1 -20

How Do you select group that doesnt contain certain value but must have specific values

I have table Order
ID | State |
===================
1 | A |
1 | B |
1 | C |
1 | D |
1 | E |
2 | A |
2 | B |
2 | E |
3 | A |
3 | B |
3 | E |
4 | A |
4 | B |
4 | C |
4 | D |
From where I like to select group of Ids which must have state value B and E AND must not have state value C and D.
From the above table - The right result should have id 2 and 3
Thanks,
SELECT *
FROM Order
WHERE State IN ('B','E')
That's it. The fact that you're stating the value can only be 'B' or 'E' means you're already excluding any values of 'C' or 'D', or anything else really.
Hope this helps:
SELECT id FROM ORDER
WHERE STATE = E AND STATE = B
You may use the set operator: EXCEPT
SELECT ID FROM Order WHERE State IN ('B','E')
EXCEPT
SELECT ID FROM Order WHERE State IN ('C','D')
The following should work (there might be a better alternative using windowing functions or depending on the specific features available in your dbms)
SELECT ID FROM
(
SELECT
ID,
CASE STATE
WHEN 'B' THEN 'Y'
ELSE 'N'
END AS HasB,
CASE STATE
WHEN 'E' THEN 'Y'
ELSE 'N'
END AS HasE,
CASE STATE
WHEN 'C' THEN 'Y'
ELSE 'N'
END AS HasC,
CASE STATE
WHEN 'D' THEN 'Y'
ELSE 'N'
END AS HasD
FROM TABLE
)
GROUP BY ID
HAVING MAX(HasB) = 'Y' AND MAX(HasE) = 'Y' AND MAX(HasC) = 'N' AND MAX(HasD) = 'N'
A simple way to do this uses aggregation and a having clause:
select id
from t
where sum(case when state = 'B' then 1 else 0 end) > 0 and
sum(case when state = 'E' then 1 else 0 end) > 0 and
sum(case when state = 'C' then 1 else 0 end) = 0 and
sum(case when state = 'D' then 1 else 0 end) = 0;
Each condition in the having clause counts the number of times that a given value is present. The = 0 means there are no matches and > 0 means there is at least one.

Multiple Groupings with a sum

My Table :
ID | TIME OF CREATION | OWNER | STATE
1 2015-1-1 arpan A
2 2015-1-2 arpan B
My desired o/p from my query is :
DATE | OWNER | COUNT(STATE = A) | COUNT(STATE = B) | ...
I checked out SUM( CASE ) but you cant group by date and sum by owner right?
Stuck here. :(
Can someone help?
I think you just want conditional aggregation:
select date, owner, sum(case when state = 'A' then 1 else 0 end) as state_A,
sum(case when state = 'B' then 1 else 0 end) as state_b
from table t
group by date, owner;