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;
Related
I'm trying to see if it's possible to have several unique columns in a select statement from varying where clause selections. Here is my query.
select org_id, count(org_role) as total
from organization
where org_id = 10 and org_role = 9
group by org_id;
the above works perfectly. It produces:
org_id total
10 19
Id'd like to add another column count named total2 where org_id = 10 and org_role = 7 (the count is 23). So i'd have this result:
org_id total total2
10 19 23
I'm just not sure how to edit the original above query to produce that. Any thoughts would be appreciated.
You can use conditional aggregation. For example:
select
org_id,
sum(case when org_role = 9 then 1 else 0 end) as total,
sum(case when org_role = 7 then 1 else 0 end) as total2
from organization
where org_id = 10 and org_role in (7, 9)
group by org_id;
select org_id, count(org_role) as total, count(total_2)
from organization
where org_id = 10 and org_role = 9
group by org_id;
If it does not work please send your database structure.
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';
I have this table
**applications**
id user_id company_id shortlisted
1 10 99 0
2 10 100 1
3 10 101 1
4 10 102 0
5 11 99 1
6 12 99 0
6 12 101 0
What I want is to select all users
which have been shortlisted at-least once
which have not been shortlisted at all
For the first case, i have the following query:
SELECT user_id
from applications
where shortlisted=1
Group
By user_id
and this gives me the expected result like below
**applications**
user_id
10
11
But I'm trying the following query for the second case and it returns me an empty set:
Select user_id
from applications as Application
where shortlisted=0
and NOT EXISTS(Select user_id from applications where user_id=Application.user_id and shortlisted=1)
What am i missing?
PS: Please ignore any typos as i typed them manually for this post.
To get both results in a single query simply use aggregation:
select user_id, max(shortlisted) as was_shortlisted
from applications
group By user_id
You can use group by and having for both.
For the first:
select user_id
from applications
group By user_id
having max(shortlisted) = 1;
For the second:
select user_id
from applications
group By user_id
having max(shortlisted) = 0;
In all honesty, your version with the where is more efficient for the first query. This is just to show how closely related the queries are.
You can try following query;
select user_id from table1
group by user_id having MIN(shortlisted) = 1
This will give you to at least have shortlisted = 1 condition and don't have shortlisted = 0 records.
I previously posted a question here: Mysql query with joined tables problems
but didn't get good answers, so I thought I break it down to show only the part that gives me a headache, I might get answers faster to this question, and if I can solve this, I can solve the previous problem too.
The values are referring to an item_id, and I want to get item_id's where the item is referring to (('good' OR 'bad') AND 'fast')
So item_id 1 must be listed, because it is good and also fast
item_id 2 should not listed because it is not fast.
The result i want to get
item_id
1
5
if I have a table like this
id item_id value
1 1 'good'
2 1 'fast'
3 2 'good'
4 2 'slow'
5 3 'good'
6 3 'slow'
7 4 'bad'
8 4 'slow'
9 5 'bad'
10 5 'fast'
11 6 'moderate'
12 6 'fast'
Can someone help me?
One way to see this is: you want a statement per item, so you aggregate and group by item. Criteria come in the HAVING clause.
select item_id
from mytable
group by item_id
having count(case when value = 'fast' then 1 end) >= 1
and count(case when value in ('good','bad') then 1 end) >= 1;
(You can also use sum(case when value = 'fast' then 1 else 0 end) >= 1 or max(case when value = 'fast' then 1 else 0 end) = 1 or some expression along those lines. COUNT(expression) counts expressions that are not null. As I am omitting an ELSE branch, a non-matching record results in null and is thus not counted. Some prefer SUM, some prefer COUNT - it's finally a matter of personal preference.)
One way to do this is with an EXISTS query.
Here's an example:
select t1.item_id
from your_table t1
where t1.value = 'fast'
and exists (
select NULL
from your_table t2
where t2.item_id = t1.item_id
and t2.value in ('good','bad')
);
Considering that a item can be good or bad, not both, I would use the simple way:
select item_id your_table
where value in ('good','bad','fast')
group by item_id
having count(*) = 2
count should be always 2 in those cases.
I am trying to compare 2 rows and display the same ones.I did browse but was not able to find the right solution.
Table A
Count status Division
20 A 1
30 B 2
10 c 1
12 z 1
From the above table I want to display whose division is same.
Count status Division
20 A 1
10 c 1
12 z 1
Try this
Select * from TableA
Group By Division
Having Count(*) > 1
Select * from TableA
Group By Division
having Count(*) = 1
Here i used case statement , it worked for me
select CompanyCode ,'Commission Pec', Year
,sum(case when CommissionType='Commission Recevied' then JAN else 0 end)/sum(case when CommissionType='Net Payments from WM' and isnull(JAN,0)<>0 then JAN else 1 end)
from Commission_Consolidate
group by CompanyCode,Year
end