Try simple:
SELECT *, 'FALSE' As is_book
FROM cars c
WHERE NOT EXISTS (
SELECT * FROM book_cars b
WHERE b.car_id=c.id AND book = 't'
)
you can also use a subquery:
SELECT *
FROM (
SELECT cars.*,
CASE WHEN EXISTS (
SELECT book_cars.* FROM book_cars
WHERE book_cars.car_id=cars.id AND book='t')
THEN 'TRUE' ELSE 'FALSE' END AS is_book
FROM cars
) x
WHERE is_book='FALSE';
EDIT
The problem in your query is in WHERE clause in the last line below:
SELECT cars.*,
CASE WHEN EXISTS (
SELECT book_cars.* FROM book_cars
WHERE book_cars.car_id=cars.id AND book='t')
THEN 'TRUE' ELSE 'FALSE' END AS 'is_book'
FROM cars
WHERE is_book='FALSE';
In standard SQL WHERE clause doesn't see any expression (or "column") declared in the SELECT clause, it can only see columns from tables in the FROM clause.
is_book column is declared in the SELECT clause, so WHERE cannot see it.
If you use a subquery, like:
SELECT *
FROM ( --- subquery
SELECT some_expression AS new_column
FROM ....
) x
WHERE new_column = 111
then the outer query sees that new column.
You can also use HAVING clause:
SELECT cars.*,
CASE WHEN EXISTS (
SELECT book_cars.* FROM book_cars
WHERE book_cars.car_id=cars.id AND book='t')
THEN 'TRUE' ELSE 'FALSE' END AS 'is_book'
FROM cars
HAVING is_book='FALSE';
because HAVING, in contrast to WHERE, does see columns declared at SELECT level.
'is_book'tois_book(without the').is_bookdoes exist?bookoris_book? if you run on your postgres db ->select is_book from YourTable, runs ok?