Reputation: 4869
Say I have a table named people
with various attributes
I would like to make a query that will return all people
, however, under a certain condition (a separate subquery) I would like for certain columns of the select statement to be set to null for redacting purposes.
So, say I have the basic query:
SELECT first_name, last_name, age, phone, address
FROM people;
Which would return a table similar to:
|first_name|last_name|age|phone|address |
------------------------------------------------
|Joe |Someone |12 |123 |1234 Somewhere|
|Bob |Other |45 |982 |4321 Somewhere|
I would like to be able to do something like this:
SELECT
first_name,
last_name,
if(people.field IN (
SELECT other_table.some_id FROM other_table WHERE other_table.field = 'is good')
)
age, phone, address
else
NULL
FROM people;
With the result I would like to have:
|first_name|last_name|age |phone|address |
------------------------------------------------
|Joe |Someone |12 |123 |1234 Somewhere|
|Bob |Other |NULL |NULL |NULL |
Is this even possible?
Upvotes: 2
Views: 1837
Reputation: 1270431
You can accomplish this with a lateral join:
select p.first_name, p.last_name, s.*
from people p left join lateral
(select p.age, p.phone, p.address
from othertable ot
where ot.other_id = p.field
) s;
The subquery will return no rows if there is not a match -- hence all the columns will be NULL
. Otherwise, it will return the fields from people
.
Upvotes: 1
Reputation: 2060
I would recommend using a solution based on EXISTS
which will be able to support any kind on multiplicity in other_table
.
Note: you usually want to "link" values from people
with values from other_table
by referencing the correct fields in the sub-query, which I have done for first_name
and last_name
.
SELECT
first_name,
last_name,
CASE WHEN MyCondition THEN NULL ELSE age END AS Age,
CASE WHEN MyCondition THEN NULL ELSE phone END AS Phone,
CASE WHEN MyCondition THEN NULL ELSE address END AS Addess
FROM (
SELECT people.*, EXISTS (SELECT 1 FROM other_table WHERE field = 'is good' AND first_name = P.first_name and last_name=P.last_name) as MyCondition
FROM people P
) MyTable
PS: in case you want to extend this to other DBMS, remember that some may not support EXISTS(...)
at the place where I typed it (example of such DBMS: Oracle).
In such a case, you need to do a CASE WHEN EXISTS(...) THEN 1 ELSE 0 END
instead.
Upvotes: 2
Reputation: 222582
It should be possible to solve this by puting the subquery in a LEFT JOIN
and then using CASE
in the SELECT
clause to set the output columns to NULL
when needed :
SELECT
p.first_name,
p.last_name,
CASE WHEN s.some_id IS NOT NULL THEN p.age END AS age,
CASE WHEN s.some_id IS NOT NULL THEN p.phone END AS phone,
CASE WHEN s.some_id IS NOT NULL THEN p.address END AS address
FROM people p
LEFT JOIN other_table s ON s.some_id = p.field AND s.field = 'is good'
The thing that you need to be careful about is the cardinality of the join. If several records in other_table
match a single people
record, then you will get duplicated output rows. To avoid that, one solution would be to use SELECT DISTINCT
, or to turn on aggregation by adding clause GROUP BY p.first_name, p.last_name, p.age, p.phone, p.address
at the end of the query.
Upvotes: 2