Where Clause on same column twice with different condition - mysql

Table1: Agent Data: where agent details are stored
Agent Table
Agent_Id Name
1 Vijay
2 Rajesh
3 Satish
4 Anji
Table2: Case_transaction_details: Each step in Backend operation is stored.
Case_transaction_details
Case_Id Stage Login_Time Logout_time Agent_id Status
101 Maker 5/11/2019 10:20 10:30 2 Success
102 Maker 10:25 10:35 1 Success
103 Maker 10:40 10:50 2 Success
101 Checker 10:45 11:00 3 Success
101 Approver 11:15 11:30 2 Success
102 Checker 10:50 11:00 1 Reject
102 Maker 11:15 11:45 4 Reverify
103 Checker 11:30 11:40 2 Reject
The question is how to get Case Id which is rejected by checker but still not reverified?
SELECT Case_Id
FROM Case_transaction_detail
WHERE Status = 'Reject' and status != 'Reverify';
How to apply where clause twice on same column?
trying the above query is giving both
102
103
whereas answer should be only 103

You could use:
SELECT Case_Id
FROM Case_transaction_detail
GROUP BY Case_Id
HAVING SUM(Status = 'Reject') > 0
and SUM(status = 'Reverify') = 0 ;

I think you want aggregation:
SELECT Case_Id
FROM Case_transaction_detail
GROUP BY Case_Id
HAVING SUM(Status = 'Reject') > 0 AND
SUM(status = 'Reverify') = 0;
MySQL treats boolean conditions as numbers in a number context, with "1" for true and "0" for false. So, the first condition counts the number of rejects; the > 0 says there is at least one.
Similarly, the second condition counts the number of reverifies for each case. The = 0 says there are none.

You could do this with a simple LEFT JOIN.
Basically, you will select from the table all the rejected CaseIds, and you will left join the same table using the CaseIds selecting only their associated reverifieds.
The ones you want will be the ones where the left join relation (the associated reverifieds) is NULL.
SELECT CaseRejected.Case_Id
FROM Case_transaction_detail CaseRejected
LEFT JOIN Case_transaction_detail CaseReverified ON (CaseReverified.Case_Id = CaseRejected.Case_Id AND CaseReverified.Status = 'Reverify')
WHERE CaseRejected.Status = 'Reject'
AND CaseReverified.Case_Id IS NULL;

One way would be to test for homogeneity in the HAVING clause
SELECT Case_Id
FROM Case_transaction_detail
GROUP BY Case_Id
HAVING AVG(Status='Rejected')=1
Another method is basically a hack using GROUP_CONCAT
SELECT Case_Id
FROM Case_transaction_detail
GROUP BY Case_Id
HAVING GROUP_CONCAT(DISTINCT Status))='Rejected'

SELECT Case_Id
FROM case_transaction_details
GROUP BY Case_Id
HAVING SUM(Status = 'Reject') - SUM(status = 'Reverify') = 1

SELECT
case_id
FROM
case_transaction_details
WHERE
status = 'Reject'
AND status <> 'Reverify';

Related

Is there way I can SELECT and JOIN COUNT different queries?

I'm using MYSQL and I have a message table like below.
id
parent_id
sender_id
receiver_id
content
readed
sender_deleted
receiver_deleted
created
18
0
6
1
testab
0
0
0
2021-10-28 01:13:42
19
18
6
1
testcd
0
0
0
2021-10-28 01:14:55
I'm trying to combine two queries in one. Selecting and count where readed value is 0.
This query is selecting query.
SELECT * FROM message
WHERE (sender_id = 1 OR receiver_id = 1) AND (id = 18 OR parent_id = 18);
And this query is counting query.
SELECT COUNT(id) FROM message
WHERE (sender_id = 1 OR receiver_id = 1)
AND (id = 18 OR parent_id = 18) AND (readed = 0);
I'm trying to combine these two using LEFT JOIN.
SELECT a.id, a.parent_id, a.content, COUNT(b.id) AS unreaded_message
FROM message a
LEFT JOIN message c ON a.id = c.id AND (readed = 0)
GROUP BY A.ID, A.Date
ORDER BY a.id;
But I'm getting error like below.
ERROR 1054 (42S22): Unknown column 'b.id' in 'field list'
Is there way I can left join count query?
I notice these issues when testing the query:
The incorrect alias of b.id for the COUNT(). That's where the error is indicating.
The non-existing A.Date from table message. Based on your table sample, you don't have a column named as Date. Instead you have a column named created that stores date+time.
The query itself is incompatible with sql_mode=only_full_group_by. Since MySQL v5.7.5, this setting is on by default, with a very good reason of - "if the only_full_group_by mode is turned off the server is free to choose any value from each group, so unless they are the same, the values chosen are nondeterministic, which is probably not what you want (refer: "MySQL Handling of Group By" docs.
Now, if I'm not mistaken, content stores the text messages, correct? And since id=19 parent is id=18, it should be in the same row, with the total count of unread message is 2. I'm not sure if that's what you're really looking for but I'll post two queries; one is to address your current issue and another to suggest that it maybe what you're looking for.
For your current issue, you can achieve the desired result without self-join, and instead of using COUNT(), you can use SUM() with CASE expression like below:
SELECT id, parent_id, content,
SUM(CASE WHEN readed=0 THEN 1 ELSE 0 END) AS unreaded_message
FROM message
GROUP BY id, parent_id, content;
COUNT() will take every row in the query result depending on your conditions. The replacement of SUM() with CASE expression here is just telling the query to:
SUM(CASE WHEN readed=0 THEN 1 ELSE 0 END) AS unreaded_message
-- if the readed column is 0 (zero) then give it 1, else give it 0 then add them up.
The second suggestion I have is this, let's assume you have more rows in the table like this:
id
parent_id
sender_id
receiver_id
content
readed
sender_deleted
receiver_deleted
created
18
0
6
1
testab
1
0
0
2021-10-28 01:13:42
19
18
6
1
testcd
1
0
0
2021-10-28 01:14:55
20
18
6
1
testde
0
0
0
2021-10-28 01:15:05
21
0
6
1
testfg
0
0
0
2021-10-28 02:34:11
22
21
6
1
testhi
0
0
0
2021-10-28 02:44:01
With id of 18,19 both have readed=1, the query you have and the one I suggested above will return result like this:
id
parent_id
content
unreaded_message
18
0
testab
0
19
18
testcd
0
20
18
testde
1
21
0
testfg
1
22
21
testhi
1
But I have a feeling that you probably want something like this:
m_id
contents
unreaded_message
18
testde
1
21
testgftesthi
2
If that's a possibility, then you can just run this query:
SELECT CASE WHEN parent_id=0 THEN id ELSE parent_id END AS m_id,
GROUP_CONCAT(CASE WHEN readed=0
THEN content ELSE '' END
ORDER BY readed, id SEPARATOR '\r\n' ) AS contents,
SUM(CASE WHEN readed=0 THEN 1 ELSE 0 END) AS unreaded_message
FROM message
GROUP BY m_id;
Demo fiddle
You are using in the query B alias in the "COUNT" satement. You need to use A or C alias like these example:
SELECT a.id, a.parent_id, a.content, COUNT(c.id) AS unreaded_message
FROM message a
LEFT JOIN message c ON a.id = c.id AND (readed = 0)
GROUP BY A.ID, A.Date
ORDER BY a.id;

SQL Query to filter rows using a sub query which queries the same table

I am trying to build a query which filters rows based on other rows as in the following example
TableA
Id status type date
300 approved ACTIVE 11/12/2015 10:00:00
300 approved ACTIVE 11/12/2015 10:10:00
300 approved INACTIVE 11/12/2015 11:00:00
200 approved ACTIVE 11/12/2015 11:10:00
200 approved INACTIVE 11/12/2015 11:10:00
100 approved ACTIVE 11/12/2015 11:10:00
From the above table I am trying to return Ids that have equal number of ACTIVE and INACTIVE types like Id 300 has two rows with type ACTIVE and one row with type INACTIVE, so Id 300 should be excluded from my results where as 200 has 1 active and 1 inactive and it should be included in the results
In the above table status, type can have other values too but I care only the ones listed above ignoring others
So, for TableA final result of the query would be
Id
200
I tried to run the below query but that didnt give me the results I expected
SELECT Id
FROM TableA oa
WHERE oa.type in('ACTIVE','INACTIVE')
and oa.status='APPROVED'
and not EXISTS(SELECT
x.id
,COUNT(*)
FROM (SELECT DISTINCT
id
,c.type
FROM TableA c
WHERE
AND c.type IN ('ACTIVE','INACTIVE')
AND c.status = 'APPROVED'
AND c.Id= ta.Id
)x
GROUP BY x.Id
HAVING COUNT(*) = 1)
Can the above query be corrected to get the required results?
You just need to use SUM and HAVING:
SELECT Id
FROM TableA
WHERE
status = 'approved'
AND type In ('ACTIVE', 'INACTIVE')
GROUP BY Id
HAVING
SUM(CASE WHEN type = 'ACTIVE' THEN 1 ELSE 0 END) =
SUM(CASE WHEN type = 'INACTIVE' THEN 1 ELSE 0 END)

How to get count greater than and less than average values group by name

I have a data set with name and their transaction ,how to get average and count of transactions grater than that average and less than that average..
Name Transaction
John 12
John 34
John 45
John 66
John 32
chris 26
chris 54
chris 56
chris 99
chris 13
chris 4
kim 22
kim 34
kim 7
kim 11
kim 34
O/P will be
Name Avg Count_greater_than_Avg Count_Less_than_Avg
John 37.8 2 3
chris 42 3 3
kim 21.6 3 2
Thanks in advance..
Try this:
SELECT t1.Name, t2.Aver,
COUNT(CASE WHEN Transaction < Aver THEN 1 END) Count_Less_than_Avg,
COUNT(CASE WHEN Transaction > Aver THEN 1 END) Count_greater_than_Avg
FROM mytable AS t1
JOIN (
SELECT Name, AVG(Transaction * 1.0) AS Aver
FROM mytable
GROUP BY Name
) AS t2 ON t1.Name = t2.Name
GROUP By Name
You need a derived table in order to calculate the average value per Name. You can then JOIN the original table to this derived table and use conditional aggregation in order to calculate less than, greater than number of transactions.
Demo here
This basically first add a column Your_Avg using a correlated query, and then wrap it with another select to select the count of the occurrences of times smaller then avg and times larger.
SELECT tt.name,tt.Your_Avg,
count(CASE WHEN tt.Your_Avg > tt.Transaction then 1 end) as Greater_Then_Avg,
count(CASE WHEN tt.Your_Avg > tt.Transaction then 1 end) as Smaller_Then_Avg
FROM(
SELECT t.name,
(SELECT avg(s.transaction) FROM YourTable s WHERE s.name = t.name) as Your_Avg,
t.transaction
FROM YourTable) tt
GROUP BY tt.name

MySQL Query to find users still inside room

Below is my database table, where I will have Check In and Check Out entry records for attending the conference room.
id registration_id roomno day type
1 101 1 2 In
2 103 1 2 In
3 101 1 2 Out
4 105 1 2 In
5 103 1 2 Out
6 101 1 2 In
7 103 1 2 In
8 101 1 2 Out
9 105 1 2 In
10 103 1 2 Out
Now, I want to select those records, which are still attending the conference. Condition is like their last record should be type = In. There can be multiple In/Out entries for each user during a day.
Please let me know the quickest possible MySQL query.
Thanks
Answer which I ended up using:
select * from `registrations_inouts` t
group by t.registration_id
having max(id) = max(case when type = 'In' then id end)
order by rand() limit 1;
Here is one method using not exists:
select *
from t
where t.type = 'In' and
not exists (select 1
from t t2
where t2.registration_id = t.registration_id and t2.type = 'Out'
);
Another method uses conditional aggregation:
select t.registration_id
from t
group by t.registration_id
having max(id) = max(case when type = 'In' then id end);
Note: both of these assume that the ids are assigned sequentially in time, so larger ids are later in time.

ONE SQL query to count records on different conditions

How can I count the total number of records, the number of unique of users and number of records on which the status is 2 from the table participants in one query?
I know how to accomplish this using 3 separate queries:
SELECT COUNT() FROM participants
SELECT COUNT() FROM participants GROUP BY user
SELECT COUNT(*) FROM participants WHERE status = 2
But this doesn't really seem efficient?
Table participants
id user status
10 john#example.com 1
11 john#example.com 1
12 john#example.com 1
13 sally#mailing.com 1
14 sally#mailing.com 2
15 edward#halloworld.com 1
16 edward#halloworld.com 1
17 edward#halloworld.com 2
18 mike#bestmail.net 2
19 mike#bestmail.net 1
29 nat#worldcom.com 0
Just use conditional aggregation:
select count(*) as numrecords, count(distinct user) as numusers,
sum(status = 2) as numstatus_2
from participants p;
Since you want just one result (per requirement), you don't need a group by clause at all, and all of these requirements can be created as arguments for the count function:
SELECT COUNT(*) AS total_records,
COUNT(DISTINCT user) AS distinct_users_count,
COUNT(CASE status WHEN 2 ELSE NULL END) AS status_2_count
FROM participants