Merge two SELECT queries into one - sql

I have two queries where I only need the count of total records but the only difference in the queries is one field value.
Example;
SELECT COUNT(*) AS group_a
FROM tbl
WHERE category = 'value_a'
SELECT COUNT(*) AS group_b
FROM tbl
WHERE category = 'value_b'
How can I get something like this: (pseudo)
SELECT COUNT(*) AS group_a, COUNT(*) AS group_b
FROM tbl
WHERE category IN ('value_a', 'value_b')
But the results are like this
group_a , group_b
56, 101
I was thinking a CASE statement in the query to filter the two but how do I implement it? or is there a better way?
I'm doing a UNION right now but wanted to know if I could return one record with two results

select sum(case when category = 'value_a' then 1 else 0 end) as group_a,
sum(case when category = 'value_b' then 1 else 0 end) as group_b
from tbl
where category in ('value_a', 'value_b')

select sum(case when category = 'value_a' then 1 else 0 end) group_a,
sum(case when category = 'value_b' then 1 else 0 end) group_b
from tbl

SELECT category,COUNT(*) FROM tbl
GROUP BY category;
That expands to more categories. If you want just those categories
SELECT category,COUNT(*) FROM tbl
WHERE category IN ('value_a', 'value_b')
GROUP BY category;

What strange answers for counting. Here's a straightforward COUNT:
SELECT COUNT(category = 'value_a' OR NULL) AS group_a, COUNT(category = 'value_b' OR NULL) AS group_b FROM tbl;
The COUNT aggregate in PostgreSQL allows complex syntax like I've shown. Note that the OR NULL is quite essential as COUNT counts only those rows for which the condition category = '...' OR NULL gives non-NULL answer.

Just for the fun of it:
SELECT *
FROM
(
SELECT category
FROM tbl
) subquery
PIVOT
(
COUNT(category)
FOR category IN ([value_a],[value_b])
) AS piv

Related

Aggregate two value when a condition is met

Edit: I need to partition by ID and Month
I have the table below:
TableA1 50 low 201803 20
I would like to multiple hoursxWorkingDaysInMonth when Cat = 'low'.
ID Hours Cat Month WorkingDaysInMonth
I have the SQL below, but it doesn't account for the condition
SELECT SUM(HOURS * MONTH) OVER (PARTITION BY ID, MONTH) AS TESTING,
FROM TABLEA
You would seem to want:
SELECT SUM(A.HOURS * A.WORKINGDAYSINMONTH) AS AMT
FROM TABLEA A
WHERE cat = 'low';
If you want the logic on each row:
select a.*,
(case when a.cat = 'low' then a.hour * a.workingdaysinmonth end) as amt
from tablea a;
SELECT CASE WHEN cat = 'low' THEN HOURS * WORKINGDAYSINMONTH END AS AMT
FROM TABLEA
SELECT DECODE(CAT,'low',HOURS * WORKINGDAYSINMONTH END) AS AMT
FROM TABLEA
You can use a CASE or DECODE statement to do this work.
In case if you want to add a default to the rest of the rows you can have else statement in your query like this
SELECT CASE WHEN cat = 'low' THEN HOURS * WORKINGDAYSINMONTH
ELSE 0 END AS AMT
FROM TABLEA

How to case handle a field in Group by

I am trying to group the below CTE based on StudentID and I would like to compute the result with a rule like, if he passes in one subject he is passed overall , if not failed.
WITH mycte(StudentId,SubjectId,Result) as
(SELECT 1,1,'pass'
UNION ALL SELECT 1,2,'fail'
UNION ALL SELECT 1,3,'pass'
UNION ALL SELECT 2,1,'fail'
UNION ALL SELECT 2,2,'fail'
UNION ALL SELECT 3,1,NULL
)
Can you help me in understanding how to achieve this logic.
Expected Result is like
StudentID Result
1 pass
2 fail
3 NULL
Try this simple way
SELECT StudentId,
Result = Max(Result)
FROM mycte
GROUP BY StudentId
Trick here is Pass will be ordered after Fail in string ordering. So when you use Max aggregate we will get Pass if at least one Pass is present
You can aggregate over students and count the number of passes. According to your logic, if even one pass is seen then the student should be reckoned as passing overall.
SELECT DISTINCT
t1.StudentId,
t2.Result
FROM mycte t1
LEFT JOIN
(
SELECT
StudentId,
CASE WHEN SUM(CASE WHEN Result = 'pass' THEN 1 ELSE 0 END) > 0
THEN 'pass'
WHEN SUM(CASE WHEN Result = 'fail' THEN 1 ELSE 0 END) > 0
THEN 'fail'
ELSE NULL END AS Result
FROM mycte
GROUP BY StudentId
) t2
ON t1.StudentId = t2.StudentId

How to get join multiple queries

In this http://sqlfiddle.com/#!6/aa0e17/4 as you can see id is primary key and auto incremented and values column is int type. To retrieve count based on value I am doing 4 different queries
select count(id) from status where value=1
select count(id )from status where value=2
select count(id) from status where value=3
select count(id) from status where value=4
My requirement is to get all those counts in a single query.
Why I want?
The above table is just a demo table and have only 4 queries but in my scenario I have 35 queries and so I have to do 35 methods in java.
Expected output: 4,,4,4,4 (1st query result, 2nd query result, 3rd query result, 4th query result)
select value, count(id)
from status
group by value
Here are the 2 normal ways of solving it:
Example 1 PIVOT:
SELECT [1] count1,[2] count2,[3] count3,[4] count4
FROM
(
SELECT id, value
FROM status
) p
PIVOT (COUNT(id) FOR [value] IN ([1], [2], [3], [4])) AS pvt
Use CONCAT if you want to combine the columns into one.
To do this, replace first row in first example with:
SELECT CONCAT([1],',',[2],',',[3],',',[4])
Example 2 CASE:
SELECT
COUNT(CASE WHEN value = 1 THEN 1 END) count1,
COUNT(CASE WHEN value = 2 THEN 1 END) count2,
COUNT(CASE WHEN value = 3 THEN 1 END) count3,
COUNT(CASE WHEN value = 4 THEN 1 END) count4
FROM status
You should better count rows and group by the value by the following query:
SELECT COUNT(*) FROM status GROUP BY value
or for a better description and look try this:
SELECT value, COUNT(*) AS COUNT FROM status GROUP BY value
Use UNION (or UNION ALL to preserve duplicate values) like:
select count(id) from status where value=1
UNION
select count(id )from status where value=2
UNION
select count(id) from status where value=3
UNION
select count(id) from status where value=4
Have a look at a similar question here: https://stackoverflow.com/a/6066234
[Edit 1]
Check the fiddle, it works on my machine ;) http://sqlfiddle.com/#!6/b89ef/1/0
Since I removed a (3) from the insert, you get 4,3 (I'm only selecting fours and threes here).
[Edit 2]
I did not catch the part where you wanted it all on one line.
Just wrap a SELECT around your statements like http://sqlfiddle.com/#!6/aa0e17/34/0:
select
(select count(id) from status where value=1),
(select count(id) from status where value=2),
(select count(id) from status where value=3),
(select count(id) from status where value=4)
;
And your result is one row with 4,4,4,4 as result.
If what you're looking for is a comma-delimited string, then this might be helpful:
WITH CTE(N) AS(
SELECT COUNT(ID) FROM STATUS WHERE VALUE=1 UNION ALL
SELECT COUNT(ID )FROM STATUS WHERE VALUE=2 UNION ALL
SELECT COUNT(ID) FROM STATUS WHERE VALUE=3 UNION ALL
SELECT COUNT(ID) FROM STATUS WHERE VALUE=4 UNION ALL
)
SELECT STUFF((
SELECT N', ' + CONVERT(VARCHAR(10), N)
FROM CTE FOR XML PATH(''), TYPE
).value('text()[1]','nvarchar(max)')
, 1 , 2 , N'')

Multiple where clauses in one row sql

I want to take the below statement and fuse it into one query.
SELECT COUNT(*) AS count1 WHERE Month='11' AND Flag = 1
SELECT COUNT(*) AS count2 WHERE Month='11' AND Flag = 2
SELECT COUNT(*) AS count1 WHERE Month='12' AND Flag = 1
SELECT COUNT(*) AS count2 WHERE Month='12' AND Flag = 2
I want this to display as one query with columns count1 and count2 and rows month 11 and month 12.
Is there a syntax for this?
You can combine SUM and CASE to get various counts in one go:
SELECT
Month,
SUM(CASE WHEN Flag=1 THEN 1 ELSE 0 END) as count1,
SUM(CASE WHEN Flag=2 THEN 1 ELSE 0 END) as count2
from
...
WHERE Month in ('11','12')
GROUP BY
Month /* Other columns? */
With two columns only, it can be something like this:
select
(SELECT COUNT(*) FROM tablename WHERE Month='11' AND Flag = 1) as 'count1'
(SELECT COUNT(*) FROM tablename WHERE Month='11' AND Flag = 2) as 'count2'
UNION ALL
select
(SELECT COUNT(*) FROM tablename WHERE Month='12' AND Flag = 1),
(SELECT COUNT(*) FROM tablename WHERE Month='12' AND Flag = 2)
Replace tablename with the name of your table.
How about this:
select
month, flag, count(*)
from
table
where
month in ('11', '12') and
flag in (1, 2)
group by
month, flag;

SQL Select for multiple where clause

I am trying to create SQL Select that returns counts of a certain field based on a field.
So, here is what I am trying to do.
Select count(distinct id) as TotalCount, -- this will be the total of id
count(distinct id where type='A') as TotalA, -- this will be total when type='A'
count(distinct id where type='B') as TotalB -- This will be total when type = 'B'
from MyTable
Basically, TotalCount = TotalA + TotalB.
How can I achieve this in SQL Select Statement?
Thanks.
Select count(distinct id) as TotalCount, -- this will be the total of id
count(distinct case type when 'A' then id else NULL end) as TotalA,
count(distinct case type when 'B' then id else NULL end) as TotalB
from MyTable;
Of course TotalCount may or may not be TotalA + TotalB, depending on the actual data.
You can do it like that:
SELECT
count(distinct id) as TotalCount,
sum(CASE WHEN type = 'A' THEN 1 ELSE 0) as TotalA,
sum(CASE WHEN type = 'B' THEN 1 ELSE 0) as TotalB,
FROM
MyTable
Count per type:
SELECT
type,
count(DISTINCT id)
FROM
MyTable
GROUP BY
type
Why not simply UNION the separate queries.
Select 'all' as which, count(distinct id) as Total from mytable
union
select 'a' as which, count(distinct id) where type='A' as Total from mytable
union
select 'b' as which, count(distinct id) where type='B' as Total from mytable