Complaints Database Design-SQL Query to show All rows - sql

I have an application where I am showing all complaints to my Logged In agents.
I have 100 of agents who can see the same complaint screen.for example agentA and agentB
can see all the complaints when they logged in.
> Complaint_id Complaint_detail
1 complaint_1
2 complaint_2
3 complaint_3
Now the problem is I have to add functionality that every agent can put comments for their ease or you can say a reminder like (agentA put comment : i will work on this comment tomorrow). so this comment will display to only agentA.
for this implementation I have created a new table named complaint_detail where I add coloumn 'comment' and 'user_id'
and to display complaints i write query
select complaint.Complaint_name,complaint.User_ID from complaint
left outer join complaint_detail on complaint.Complaint_id = complaint_detail.complaint_id
this query display all the records now when I filter on user it will show only that users record to solve this I add
select * from (select complaint.Complaint_name,complaint.User_ID from complaint
left outer join complaint_detail on complaint.Complaint_id = complaint_detail.complaint_id
complaint_detail.complaint_info_id
) asdf
where user_id = 'agentA'
or User_ID is null
select * from (
select complaints.complaint_id,complaints.complaint_detail, complaints_detail.comment,complaints_detail.user_id from complaints
left outer join complaints_detail on complaints.Complaint_id = complaints_detail.complaint_id
) asdf
where user_id = 'agentA'
or User_ID is null
is
complaint_id complaint_detail comment user_id
1 complaint_1 complaint_1 agentA
2 complaint_2 complaint_2 agentA
3 complaint_3 null null
for agentB
complaint_id complaint_detail comment user_id
1 complaint_1 complaint1_ agentB
3 complaint_3 null null
any idea how can i achieve this that every user can see all complaints and only their comments.should i change table structure or query can do this ?

Something like this should do it:
select * from complaints cmp
left outer join comments com on cmp.id=com.complaint_id
and com.user_id='agentA' or com.user_id is null
This will get data from comments table related to complaint if it exists (left join)
and limit comments to those of the agent or without a user id on the comment
Of course you can specify columns in the select if you don't want to retrieve all columns from the complaints & comments tables.

Related

Get only users who do not have the id equal to a condition (SQL)

I have two tables, user:
id
full_name
1
Beatriz
2
Mauro
3
Jose
4
fran
approver :
id
subordinate_id
approver_id
1
1
2
2
3
4
I would like to bring up the names of people who are not registered in the subordinate_id column
I did the following query:
SELECT
U.full_name
FROM user AS U
INNER JOIN approver as A
ON U.id <> A.subordinate_id ;
enter image description here
and still users are coming in that are in the subordinate_id column of the approver table.
I would like to get the result only for user names that are not subordinate_id, can someone help with this?
I would like a result with only the users that are not subordinate_id
This is simple to accomplish an ansi-sql with a not exists semi join:
Select full_name
from user u
where not exists (
select * from approver a
where a.approver_id = u.id <-- or (subordinate_id, whichever it should be)
);

Joining two tables where some columns merge and others must be null

I feel like this question must have already been answered somewhere but my searching has not turned up anything relevant. If anyone is able to link to another answer I can accept this being marked as a duplicate and closed.
I have three tables like this:
users(id)
things1(id, user_id, thing1_text)
things2(id, user_id, thing2_text)
For the purpose of this example, assume there's only one user in the users table with an id of 1.
Let's say things1 looks like this:
id
1
2
user_id
1
1
thing1_text
im a thing 1
im a thing 1 too
And things2 looks like this:
id
1
2
user_id
1
1
thing2_text
im a thing 2
im a thing 2 too
I'm trying to create the query which will return this:
user_id
1
1
1
1
thing1_text
im a thing 1
im a thing 1 too
NULL
NULL
thing2_text
NULL
NULL
im a thing 2
im a thing 2 too
My first, admittedly naive, attempt looked like this:
select users.id as user_id
, things1.thing1_text
, things2.thing2_text
from users
full outer join things1
on things1.user_id = users.id
full outer join things2
on things2.user_id = users.id;
However this doesn't put NULL in any of the fields and instead combines them all - which I'm sure the more SQL minded among you probably figured when you read the query :D
Anyway. This is where I'm at. Any help at all would be greatly appreciated.
You seem to want union all. Start with this:
select user_id, thing1_text, thing2_text
from ((select user_id, thing1_text, NULL as thing2_text
from things1 t1 join
users u
on t1.user_id = u.id
) union all
(select user_id, NULL, thing2_text
from things2 t2 join
users u
on t2.user_id = u.id
)
) tt
order by user_id;

To display only the active status for one specific id and for same id all status should be disabled

I want to display person list who are Active for only one application starting 'a' and all other application should be 'DISABLED'.
Person id is in one table and application details will be in another table.
Have to select the Person id who is satisfies the following condition. I have attached the model result in which I have joined the three table . I need to select user as below(Highlighted),
person_id is a primary key.
The query used as follows:
SELECT * FROM (select p.person_id from ur_username u join ur_username_person up on u.username_id=up.username_id
join ur_person p on up.person_id=p.person_id
WHERE ( U.USERNAME LIKE 'A-%' OR U.USERNAME LIKE 'a-%')
AND u.status='ACTIVE' AND U.ROLE_ID =123 ) E
WHERE p.person_id IN ( select p.person_id from ur_username u join ur_username_person up on u.username_id=up.username_id
join ur_person p on up.person_id=p.person_id
WHERE ( U.USERNAME NOT LIKE 'A-%' OR U.USERNAME NOT LIKE 'a-%')
AND u.status='DISABLED' AND U.ROLE_ID =123 )
I am getting the person who is active in any other application also.
In that above table i want the username a-pri (starts with a-) also with status 'ACTIVE' all the other status for application id 123 is disabled . no other username is active for that 123 id.
We can try aggregating on the Application_id and then checking two things. First, we can check that a username a-pri who is active appears once, and only once. Second, we can assert that only one record appears as active. These two conditions would seem to meet your requirements.
SELECT
Application_id
FROM yourTable
GROUP BY
Application_id
HAVING
SUM(CASE WHEN username='a-pri' AND status='ACTIVE' THEN 1 ELSE 0 END) = 1 AND
SUM(CASE WHEN status = 'ACTIVE' THEN 1 ELSE 0 END) = 1;
Follow the link below which uses a larger sample data set to cover more edge cases.
Demo
Probably I do not correctly understand your request, but here is my code:
Select username from your_rable where status = 'ACTIVE';
If this is not what you intend to receive, please provide more dataset, maybe for more Application_id and also the needed result.

SQL query (Join without duplicates)

I have tables users and topics. Every user can have from 0 to several topics (one-to-many relationship).
How I can get only those users which have at least one topic?
I need all columns from users (without columns from topics) and without duplicates in table users. In last column I need number of topics.
UPDATED:
Should be like this:
SELECT user.*, count(topic.id)
FROM ad
LEFT JOIN topic ON user.id = topic.ad
GROUP BY user.id
HAVING count(topic.id) > 0;
but it takes 0 result. But it should not be 0.
Firstly you need to have your two tables, because you have left limited information about your table structure I will use an example to explain how this works, you should then be able to easily apply this to your own tables.
Firstly you need to have two tables (which you do)
Table "user"
id | name
1 | Joe Bloggs
2 | Eddy Ready
Table "topic"
topicid | userid | topic
1 | 1 | Breakfast
2 | 1 | Lunch
3 | 1 | Dinner
Now asking for a count against each user is done using the follwing;
SELECT user.name, count(topic.topicid)
FROM user
INNER JOIN topic ON user.id = topic.userid
GROUP BY user.name
If you use a left join, this will include records from the "user" table which does not have any rows in the "topic" table, however if you use an INNER JOIN this will ONLY include users who have a matching value in both tables.
I.e. because the user id "2" (which we use to join) is not listed in the topic table you will not get any results for this user.
Hope that helps!
use inner join and distinct
select distinct user_table.id
from user_table
inner join topics_table on topic_table.user_id = user_table.id
select u.id
, u.name
, count(b.topicName)
from user u
left join topic t on t.userid = u.id
group by u.id, u.name
You can select topic number per user and then join it with user data. Something like this:
with t as
(
select userid, count(*) as n
from topic
group by userid
)
SELECT user.*, t.n
FROM user
JOIN t ON user.id = t.userid

How to have multiple tables with multiple joins

I have three tables that I need to join together and get a combination of results. I have tried using left/right joins but they don't give the desired results.
For example:
Table 1 - STAFF
id name
1 John
2 Fred
Table 2 - STAFFMOBILERIGHTS
id staffid mobilerightsid rights
--this table is empty--
Table 3 - MOBILERIGHTS
id rightname
1 Login
2 View
and what I need is this as the result...
id name id staffid mobilerightsid rights id rightname
1 John null null null null 1 login
1 John null null null null 2 View
2 Fred null null null null 1 login
2 Fred null null null null 2 View
I have tried the following :
SELECT *
FROM STAFFMOBILERIGHTS SMR
RIGHT JOIN STAFF STA
ON STA.STAFFID = SMR.STAFFID
RIGHT JOIN MOBILERIGHTS MRI
ON MRI.ID = SMR.MOBILERIGHTSID
But this only returns two rows as follows:
id name id staffid mobilerightsid rights id rightname
null null null null null null 1 login
null null null null null null 2 View
Can what I am trying to achieve be done and if so how?
Thanks
From your comment its now clear you want a cross join (include all rows from staff and mobilerights). Something like this should do it
SELECT
*
FROM Staff, MobileRights
LEFT OUTER JOIN StaffMobileRights ON StaffMobileRights.StaffId = Staff.Id
The FROM clause specifies that we will be including all rows from the Staff table, and all rows from the MobileRights table. The end result will therefore contain (staff * MobileRights) rows.
To bring in rows from StaffMobileRights then we need a join to that table also. We use a LEFT OUTER join to ensure that we always include the left side (rows in the staff table) but we arent too bothered if no rows exist on the right side (StaffMobileRights table). If no row exists for the join then null values are returned.
What you are probably asking is to see null where is no rights. In the rectangular style that results are always returned, this is the only way to represent it with a simple join:
From PaulG's query i changed it a bit to always get everything form the STAFF table.
SELECT
*
FROM STAFF
RIGHT OUTER JOIN StaffMobileRights ON StaffMobileRights.StaffId = Staff.Id
INNER JOIN MobileRights ON MobileRights.Id = StaffMobileRights.MobileRightsId