SQL Function for Counting Multiple Variables as "Both" - sql

In this scenario there are two columns.
Column A = Case ID ( a unique ID for the record)
Column B = Gender possible values are Male, Female
Caveat
If a Case ID is associated with multiple genders it can have multiple records.
Example Data Set:
ColumnA ColumnB
Case001 Male
Case001 Female
Case002 Male
Case003 Female
data set continues...
Question: I would like to categorize results as in Case001 where there are two results as "Both". What would be the best way to apporach this solution? Is there a formula or standard way to accomplish this?
Sample Desired Data Set:
ColumnA ColumnB
Case001 Both
Case002 Male
Case003 Female
data set continues...
Thank you!
I can accomplish with case statement and sub queries. However, I expect there to be a better solution.

You can use EXISTS in a CASE statement:
select distinct
t.ColumnA,
case
when exists (
select 1 from tablename
where ColumnA = t.ColumnA and ColumnB <> t.ColumnB
) then 'Both'
else t.ColumnB
end
from tablename t

Use aggregation and a case expression:
select col1,
(case when min(gender) = max(gender) then min(gender)
else 'both'
end) as gender
from cases c
group by col1;

group by with having clauses combined by union all as below might be a good alternative :
with t( ColumnA, ColumnB ) as
(
select 'Case001', 'Male' union all
select 'Case001', 'Female' union all
select 'Case002', 'Male' union all
select 'Case003', 'Female'
)
select ColumnA, 'Both' ColumnB from t group by ColumnA having count(distinct ColumnB) = 2
union all
select ColumnA, max(ColumnB) from t group by ColumnA having count(distinct ColumnB) = 1;
ColumnA ColumnB
------- -------
Case001 Both
Case002 Male
Case003 Female
Since, there are only two possible cases for genders as having one of them or both of them
Demo

Related

How to create a pivot table in PostgreSQL

I am looking to essentially create a pivot view using PostgreSQL, such that the table below:
Column A
Column B
Happy
Sad
Sad
Happy
Happy
Sad
becomes
Count
Column A
Column B
Happy
2
1
Sad
1
2
I've been able to use case/when operators far enough such that I can see the counts under independent columns,
SELECT
COUNT(CASE WHEN column1 = 'Happy' THEN 1 END) AS column1_Happy_count,
COUNT(CASE WHEN column1 = 'Sad' THEN 1 END) AS column1_Sad_count,
COUNT(CASE WHEN column2 = 'Happy' THEN 1 END) AS column2_Happy_count,
COUNT(CASE WHEN column2 = 'Sad' THEN 1 END) AS column2_Sad_count,
COUNT(CASE WHEN column3 = 'Happy' THEN 1 END) AS column3_Happy_count,
COUNT(CASE WHEN column3 = 'Sad' THEN 1 END) AS column3_Sad_count
FROM your_table;
but am missing the step to essentially each the pair of columns vertically.
I'm unable to use extensions such as tablefunc and crosstab.
Try this:
CREATE TABLE my_table (
column_a varchar(10),
column_b varchar(10)
);
INSERT INTO my_table (column_a, column_b)
VALUES ('Happy', 'Sad'),
('Sad', 'Happy'),
('Happy', 'Sad'),
('Good', 'Bad');
WITH DataSource (col, val) AS
(
SELECT 'a', column_a
FROM my_table
UNION ALL
SELECT 'b', column_b
FROM my_table
)
SELECT uniq.val AS "Count"
,MAX(case when counts.col = 'a' then counts end) AS "Column A"
,MAX(case when counts.col = 'b' then counts end) AS "Column B"
FROM
(
SELECT DISTINCT val
FROM DataSource
) uniq
INNER JOIN
(
SELECT col
,val
,COUNT(*) counts
FROM DataSource
GROUP BY col
,val
) counts
ON uniq.val = counts.val
GROUP BY uniq.val
will give you this:
You may aggregate for ColumnA, aggregate for ColumnB then do a full join as the following:
select coalesce(A.ColumnA ,B.ColumnB) as "Count",
A.cnt as "Column A",
B.cnt as "Column B"
from
(
select ColumnA, count(*) cnt
from tbl_name
group by ColumnA
) A
full join
(
select ColumnB, count(*) cnt
from tbl_name
group by ColumnB
) B
on A.ColumnA = B.ColumnB
If the distinct values in ColumnA are the same as the distinct values of ColumnB then you can use join instead of the full join.
See demo.

Finding Specific Rows in SQL which must Includes Value From ColumnB

I have a table similar to below table. I want to select all ColumnA Values which has the Value "X" for ColumnB but also other possible ColumnB values.
ColumnA
ColumnB
One
X
One
Y
Two
Y
Two
Z
Three
X
Three
Z
So basically the query should result like this. Can you help me to achieve this?
ColumnA
ColumnB
One
X
One
Y
Three
X
Three
Z
One solution: once you know what Table1 values you want you can select them. So resolve that in a subquery. We'll alias the original table as X and the subquery as Y:
select X.*
from Table1 X
inner join
(
select
ColumnA
from
Table1
Where
ColumnB = 'X'
) Y
on X.ColumnA = Y.ColumnA
you could use min() over a window:
select columnA, columnB
from (
select *, min(columnb) over(partition by columna) mb
from t
)t
where mb = 'X';
I believe a subquery would be the simplest way.
Step 1 - find all the columnA values where columnB = 'x'
SELECT DISTINCT ColumnA
FROM table_name
WHERE ColumnB = 'x'
step 2 - select all the records where the value in ColumnA is in this list
SELECT *
FROM table_name
WHERE ColumnA in (SELECT DISTINCT ColumnA
FROM table_name
WHERE ColumnB = 'x')

Group BY on Condition basis

I have data in following way....
ColumnA ColumnB
7675 22838
7675 24907
7675 NULL
I want the results in following way.....
ColumnA ColumnB
7675 2 (need total count for Not Null value)
7675 0 (need count 0 for NULL value)
SELECT ColumnA, COUNT(ColumnB) ColumnB
FROM YourTable
GROUP BY ColumnA
UNION ALL
SELECT ColumnA, 0
FROM YourTable
WHERE ColumnB IS NULL
GROUP BY ColumnA
You could introduce a calculated column indicating whether ColumnB is null or not and use it as a grouping criterion together with ColumnA:
SELECT
t.ColumnA,
ColumnB = COUNT(t.ColumnB)
FROM
dbo.YourTable AS t
CROSS APPLY
(SELECT CASE WHEN t.ColumnB IS NULL THEN 1 ELSE 0 END) AS x (SubGroup)
GROUP BY
t.ColumnA,
x.SubGroup
ORDER BY
t.ColumnA,
x.SubGroup
;
The COUNT(t.ColumnB) expression would always be NULL for a null subgroup, and for the corresponding non-null subgroup it would return the number of the non-null entries.
select columnA,
count(columnB) as non_null_count,
sum(columnB is null) as null_count
from your_table
group by ColumnA
you could easily do with a count and sum which may be faster if there are a lot of rows rather than selecting all of the rows twice with a UNION
SELECT columna, columnb, SUM(mycount)
FROM
( SELECT *, COUNT(columnb) as mycount
FROM test
GROUP BY columnb
)t
GROUP BY mycount
ORDER BY CASE WHEN mycount = 0 THEN 1 ELSE 2 END DESC;
Fiddle Demo

T-SQL Writing a Count Statement to find two values

I am trying to get two columns to appear. I have made a union of number of tables together. These tables then appear in one table now.
After this table I know need to do a summary count of one column.
This column contains two values. So i require to get count on text value 1 and text value 2 in the column.
select count (column_name) as column_name
FROM table name
where column_name = 'value1'
But i am not sure how to add value 2 into this statement? Any help be great. Much appreciated.
You can use pivot, but I think conditional aggregation is easier in this case:
select sum(case when column_name = 'value1' then 1 else 0 end) as value1,
sum(case when column_name = 'value2' then 1 else 0 end) as value2
from table name;
If you can live with the values on two rows instead of in two columns, use group by:
select column_name, count(*)
from table name
group by column_name;
I not sure what you want but whatever I understand, I think this will help you -
select
Sum ( case when column_name = 'value1' then 1 else 0 end) as CountValue1,
Sum ( case when column_name = 'value2' then 1 else 0 end) as CountValue2
FROM table name
select column_name, count (*)
FROM
(
select column_name from table1
union all
select column_name from table2
) src
group by column_name
where column_name in ( 'value1' ,'value2')

sql query where null results get placed first

select *
from tableA
order by cast(columnA as int), column B.
This is my current query script. There is a scenario where there column A is null. And result rows where column A is null are pushed to the end.
Is there a way such that if columnA is null, put the rows before other rows where columnA is not null?
thanks.
Something along these lines should work if your dbms supports standard SQL.
select (case when columnA is null then 0 else 1 end) as sort_order, *
from tableA
order by sort_order, columnA, columnB;
Try like below... it will help you....
SELECT * FROM tableA ORDER BY (CASE WHEN columnA IS NULL THEN 1 ELSE 0 END) DESC,
CAST(columnA as int), column B
It display the NULL results before NOT NULL Results
I case of Oracle you can use order by columnA NULLS FIRST, columnB