Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group by, then select only records where every value of a boolean column is true

Tags:

sql

postgresql

I have both a MS SQL Database and a postgres database. A solution in either will work as I can translate it.

We have a customer_phone table where the relevant columns are:

id, customer_id, phone, is_bad

What I need to do is select all the customer_id's from this table that ONLY have is_bad = true. So if you have 1 good phone number and 1 bad, you shouldn't appear.

For some reason I'm struggling to find an easy way to do this, I feel like it should be deceptively simple.

This was a start that gives me at least all the customers a count of their good and bad numbers, but I'm wondering if there is a way that doesn't involve having to use subqueries and in's?

select  customer_id, is_bad, count(customer_id)
from customer_phone cp
group by customer_id, is_bad
order by customer_id desc
like image 859
jrandomuser Avatar asked Jan 26 '18 16:01

jrandomuser


People also ask

Is group by always used with count?

The GROUP BY statement is often used with aggregate functions ( COUNT() , MAX() , MIN() , SUM() , AVG() ) to group the result-set by one or more columns.

Is there a boolean data type in SQL?

There is no boolean data type in SQL Server. However, a common option is to use the BIT data type. A BIT data type is used to store bit values from 1 to 64. So, a BIT field can be used for booleans, providing 1 for TRUE and 0 for FALSE.

How aggregate function works in SQL?

An aggregate function performs a calculation on a set of values, and returns a single value. Except for COUNT(*) , aggregate functions ignore null values. Aggregate functions are often used with the GROUP BY clause of the SELECT statement. All aggregate functions are deterministic.

Is SQL true 1 or 0?

These types are synonyms for TINYINT(1). A value of zero is considered false. Non-zero values are considered true. However, the values TRUE and FALSE are merely aliases for 1 and 0.


2 Answers

The most intuitive way I've found to add over a boolean column like this is to SUM a column which is 1 when TRUE and 0 when FALSE:

CASE WHEN some_bool THEN 1 ELSE 0 END

So in your case:

SELECT id
FROM phones
GROUP BY id
HAVING
SUM(CASE WHEN NOT is_bad THEN 1 ELSE 0 END) = 0

Check out this SQL fiddle which shows the query in action.

like image 53
LondonRob Avatar answered Nov 03 '22 00:11

LondonRob


You could use the "aggregate function", bool_and.

This takes a set of inputs and returns:

true if all input values are true, otherwise false

In your case, where we want every is_bad to be true for a particular customer:

select customer_id
from customer_phone
group by customer_id
having bool_and(is_bad)
like image 22
Clodoaldo Neto Avatar answered Nov 03 '22 00:11

Clodoaldo Neto