Can I rewrite this SQL code to the querydsl one? - sql

I have sql code that's counting number of the records in db for different predicates
SELECT
count(*) as total_count,
count(notAided) as not_aided_count,
count(chatAided) as chat_aided_count
FROM (
SELECT
CASE WHEN aided_with IS NULL THEN 1 END notAided,
CASE WHEN aided_with = 'CHAT' THEN 1 END chatAided
FROM sessions
) sessions
Can I rewrite it with querydsl? I take a look to the CaseBuilder, but founded no idea how to use it in the select query

One can write:
query.select(
QSession.session.id.count().as("total_count"),
new CaseBuilder().when(QSession.session.aidedWith.isNotNull()).then(1).otherwise(Expressions.<Integer> nullExpression()).count().as("not_aided_count"),
new CaseBuilder().when(QSession.session.aidedWith.eq("CHAT")).then(1).otherwise(Expressions.<Integer> nullExpression()).count().as("chat_aided_count")
)
Which would be equivalent to the SQL:
SELECT
count(*) as total_count,
count(CASE WHEN aided_with IS NULL THEN 1 END) as not_aided_count,
count(CASE WHEN aided_with = 'CHAT' THEN 1 END) as chat_aided_count
FROM sessions

Related

CASE or IF statement in WHERE clause

How can I use CASE statement or IF statement in WHERE clause ?
I am trying to apply a check on the basis of COUNT
SELECT * FROM sometable
WHERE CASE WHEN (SELECT COUNT(*) FROM sometable s WHERE SP = 2 AND sometable.id = s.id) > 2 THEN sometable.SP IS NOT NULL END
So basically if the count of rows is more than 1 it should apply IS NOT NULL condition else it should not.
Your logic suggests something like:
SELECT s.*
FROM (SELECT s.*,
SUM(CASE WHEN sp = 2 THEN 1 ELSE 0 END) OVER (PARTITION BY id) as cnt_2
FROM sometable s
) s
WHERE cnt_2 <= 2 OR s.sp is not null;
That seems equivalent. The logic doesn't seem particularly useful though.

Count rows with and combine them with math operator

I have a table with different events for a case. I want to calculate how many times event A occurs for each case but subtract the amounts of event B
I have started with a code like this, but it does not work.
SELECT
((SELECT
case_id,
Count(*)
from database
where event = "A"
Group by case_id)
-
(SELECT
case_id,
Count(*)
from database
where event = "B"
Group by case_id)) as count,
case-id,
from database
I suspect that you want conditional aggregation:
select case_id,
( sum(case when event = 'A' then 1 else 0 end) -
sum(case when event = 'B' then 1 else 0 end)
) as diff
from database
group by case_id;

Optimizing code with multple conditions on multiple tables?

I want to check whether these customers have LEAD action or SELL action which both stay in another tables. However, It takes like forever to finish it.
create table ct_nguyendang.visitor
as
select user_id, updated_at::date,
case
when user_id in (select distinct d_visitor_id from xiti.lead_detail) then 'lead'
else 'None'
end as lead_action,
case
when user_id in (select distinct account_id from ct_nguyendang.daily_listor) then 'sell'
else 'None'
end as sell_action
I think you can use union all and aggregation:
select user_id, max(is_lead) as has_lead, max(is_sale) as has_sale
from ((select d_visitor_id as user_id, 1 as is_lead, 0 as is_sale
from xiti.lead_detail
) union all
(select account_id, 0, 1
from ct_nguyendang.daily_listor
)
) ls
group by user_id;
If you have a table of users, then you can use correlated subqueries:
select u.*,
(case when exists (select 1
from xiti.lead_detail l
where u.user_id = l.d_visitor_id
)
then 1 else 0
end) as has_lead,
(case when exists (select 1
from ct_nguyendang.daily_listor s
where u.user_id = s.account_id
)
then 1 else 0
end) as has_sale
from users u;
Note that I prefer using 1 for "true" and 0 for "false". Of course, you can use string values if you prefer.
To optimize this query, you want indexes on xiti.lead_detail(d_visitor_id) and ct_nguyendang.daily_listor(account_id).

Apply where clause within count in sql

SELECT
Rooms.Building,
Count(Rooms.Room) AS TotalApartments,
Count(Rooms.Room) AS ApartmentsOccupied
FROM
Rooms
WHERE
(((Rooms.AssetType) <> 'LC'))
GROUP BY
Rooms.Building;
I want to count Rooms.Room Where Rooms.Occupied = True (ApartmentsOccupied) but when I put this clause into my sql it also applies the where to the TotalApartments column
You can move some logic into CASE statements to do conditional summarization:
SELECT
Rooms.Building,
Count(Rooms.Room) AS TotalApartments,
Sum(CASE WHEN Rooms.Occupied = True THEN 1 ELSE 0 END) AS ApartmentsOccupied
FROM
Rooms
WHERE
(((Rooms.AssetType) <> 'LC'))
GROUP BY
Rooms.Building;
I'm not sure off the top of my head, but you might need to change that count to a SUM as well:
Sum(1) AS TotalApartments
And alternately, in some sql dialects the 'True' value is 1, so you could get away with something like this for the occupied count:
Sum(Rooms.Occupied) AS ApartmentsOccupied
You can do like this
SELECT
Building,
Count(Room) AS TotalApartments,
SUM(CASE WHEN Occupied = True THEN 1 ELSE 0 END) AS ApartmentsOccupied
FROM
Rooms
WHERE
AssetType <> 'LC'
GROUP BY
Building;

SQL : select a comparison ? eg, a boolean result?

I was wondering if something like this was possible in SQL :
select (
(select count(*) from T) = (select count(*) from T t where t.something = thing)
)
This is probably very far from the actual SQL if it is possible, I don't write database requests so often.
How could I get the result of my comparison with a single request ? Basically, if I had no time, I would just make two requests and compare the results in Java (boooooo !! I know).
Although your query should work, the following is probably faster because only a single query is needed
select total_count = thing_count
from (
select count(*) as total_count,
sum(case when something = 42 then 1 end) as thing_count
from t
) t
The above is ANSI SQL and should work in any DBMS supporting a real boolean type. In Oracle you would need to use an expression in the outer select:
select case when total_count = thing_count then 1 else 0 end
from (
select count(*) as total_count,
sum(case when something = 42 then 1 end) as thing_count
from t
) t
I would write your query like this:
SELECT (CASE WHEN (select count(*) from T) = (select count(*) from T t where t.something = thing) THEN 1 ELSE 0 END)
However, if the first T is the same as the second T then what you actually want to check is if there are any records where t.something <> thing .. right ?
In that case you could simply do :
SELECT (CASE WHEN EXISTS (select * from T t where t.something != thing) THEN 1 ELSE 0 END)