-1

This my dataset and i want to find No. of gender

name|gender|
----+------+
AA  |Male  |
BB  |Male  |
CC  |Male  |
DD  |Female|
EE  |Female|

sql query :

    select 
    gender,count(*)
from 
    schoolofit.user_request_1
group by gender

result:

gender|count|
------+-----+
Female|    2|
Male  |    3|

But i am looking for below result format

gender-1 | gender-2
-------------------
Male     | Female
3        |  2 

Note : looking for sql query with and without using Union

Learn Hadoop
  • 2,760
  • 8
  • 28
  • 60

4 Answers4

1

You can do it using filter clause :

CAST count to varchar to be able to union the gender count with the first row (male, female).

select *
from (
   select 'Male' as "gender-1", 'Female' as "gender-2"
  Union
   select CAST(count(*) filter (where gender = 'Male') as varchar) as "gender-1",
   CAST(count(*) filter (where gender = 'Female') as varchar) as "gender-2"
   from user_request_1
) as s
order by "gender-1" desc

Demo here

SelVazi
  • 10,028
  • 2
  • 13
  • 29
0

I understand that you want to convert row values of your current query result to columns

This can be achieved using CASE STATEMENT :

select 
    SUM(case when gender = 'Male' then 1 else 0 end) AS "gender-1",
    SUM(case when gender = 'Female' then 1 ELSE 0 end) AS "gender-2"
from 
    user_request_1;

Update : Based on the input and clarification :

select * from (select 'Male' AS "gender-1", 'Female' AS "gender-2"
UNION
select 
  CAST(SUM(case when gender = 'Male' then 1 else 0 end) as varchar) AS "gender-1",
  CAST(SUM(case when gender = 'Female' then 1 else 0 end) as varchar) AS "gender-2"
from user_request_1) as user_request
order by "gender-1" desc;

Here is the SQLFiddle; where I have used data provided by you in post.

Tushar
  • 3,527
  • 9
  • 27
  • 49
  • 1
    my expected output format is different. Please have a look. Gender value also one of the row – Learn Hadoop Mar 04 '23 at 11:15
  • Ok, I will add it to the query – Tushar Mar 04 '23 at 11:15
  • 1
    @Tushar You're emulating a SQL:2003 [aggregate filter](https://www.postgresql.org/docs/current/sql-expressions.html#SYNTAX-AGGREGATES) available in [PostgreSQL since 9.4](https://www.postgresql.org/docs/release/9.4.0/#AEN124521): `count(*) filter (where gender = 'Male')`. – Zegarek Mar 04 '23 at 11:24
  • Yes @Zegarek; As SO needs a output in different format. SO has already used `count(*)` – Tushar Mar 04 '23 at 11:29
  • @Zegarek; Yup; The other user has completed answer using `count(*)` :) – Tushar Mar 04 '23 at 11:45
  • 1
    @Tushar I wasn't suggesting that's *the* way to solve this but just pointing out that you're emulating something that's been long available - just letting you know you no longer need to. It's not about `count()`, it's about the `filter (where`. The `count()` could also have been used with `filter` emulation: `count(case when gender = 'Male' then 1 end)` - non-male will result in null and get discarded by the function, therefore counting only 'Male'. And vice versa, you could deploy `sum()` with a filter: `sum(1) filter (where gender = 'Male')`. – Zegarek Mar 04 '23 at 12:01
  • @Zegarek; Yup. You are right and `a kind soul guiding people to write queries in lot of ways` !! I appreciate that – Tushar Mar 04 '23 at 12:02
0

When the values can be dynamic, and not just 'Male' or 'Female' you can do:

WITH ABC as 
(  select 
     gender, 
     dense_rank() over (order by gender) r
   from user_request_1
) 
select 
  MIN(CASE WHEN r=1 THEN gender END) as "gender-1",
  MIN(CASE WHEN r=2 THEN gender END) as "gender-2"
from ABC
union all
select 
  SUM(CASE WHEN r=1 THEN 1 ELSE 0 END)::varchar as "count-1",
  SUM(CASE WHEN r=2 THEN 1 ELSE 0 END)::varchar as "count-2"
from ABC

see: DBFIDDLE

Luuk
  • 12,245
  • 5
  • 22
  • 33
0

One option to avoid using a union, you can use an array then unnest it as the following:

select unnest(mcnt) as gender_1,
       unnest(fcnt) as gender_2 
from
(
  select 
   array['Male', count(*) filter (where gender = 'Male')::text] as mcnt,
   array['Female', count(*) filter (where gender = 'Female')::text] as fcnt
  from table_name
) t

Demo

ahmed
  • 9,071
  • 3
  • 9
  • 22