SQL Server 2014 - Query to skip rows - sql

I have a table that has the following fields (Institution, Auditor, QuestionID, Comment). There are 5 different questions (1, 2, 3, 4, 5) and an Auditor will have made a comment/response on each question.
I need to return only those rows where an auditor has made a comment on at least one question. If no comment has been made on any question then that row needs to be skipped. So for example if Auditor 1 has made a comment on Q1 for Institution 1 then we need to see all 5 rows for Auditor 1 for that institution. If another Auditor has not made any comments yet on any questions for an institution that Auditors records for that institution needs to be skipped.
In the image above we should return the following data and skip the one shaded green because there are no comments entered for Institution B by Auditor A2 for any question
I am confused how I can do this. Maybe keep a count? Any help will be highly appreciated. Thanks.

This sounds like exists to me. It is a little hard to follow your description of the data. But based on your example, I think:
select t.*
from t
where exists (select 1
from t t2
where t2.auditor = t.auditor and
t2.institution = t.institution and
t2.comment is not null
);

Related

PostgreSQL check parent of parent in query

Okay, I'll try to be as precise as possible. I have a database with comments who have a parent_comment_id. I want to select a number of comments from this table and a matching number of answers to these comments. Here comes my problem: If I arbitrarily select comments, I might grab some who don't have any answers. However, if I select comment answers first, I might grab answers who are an answer to another comment already. So, what I want to do is grab answers who are immediate answers to a comment (parent_comment_id = NULL) and then get those comments base on the parent_comment_id. How would I go about this in a query?
Assume this layout of a database
comment_id parent_comment_id
1 NULL
2 NULL
3 1
4 3
5 1
6 3
7 1
8 4
9 NULL
10 NULL
...
Now, I would select, let's say 2 answers and the corresponding comments. If I just select the first 2 answers, I would get comment 3 and 4, but if I backtrace those, I would only get comment 1, because comment 4 is an answer to an answer. Instead, I would want to find only comments whose parent comment has no parent comment, which would be comment 3 and 5 in this example.
I haven't really tried anything beyound realizing it doesn't work without somehow recursively getting parents which I have no clue how to do in SQL queries.
I solved it with a pretty easy solution. Might be horrible practice, but works for my use-case ^^
For the given example it would be something like this:
select distinct on (parent_comment_id) c.id, c.parent_comment_id, c.text
from comments c
where parent_comment_id is not null
and (select parent_comment_id from comments p where id = c.parent_comment_id) is null
I would want to find only comments whose parent comment has no parent comment.
I think that you just want a self-join and some filtering:
select c.*
from comments c
inner join comments pc on pc.comment_id = c.parent_comment_id
where pc.parent_comment_id is null
You could also use exists:
select c.*
from comments c
where exists (
select 1
from comments pc
where pc.comment_id = c.parent_comment_id and pc.parent_comment_id is null
)

Exclude Numerous Values for SQL Server

I'm currently still learning SQL, however, I can't seem to actually find out how to exclude multiple usernames.
Example I have 2 columns at hand, 1 being username and another having the state of active or not.
UserName Status
===============
ABC Y
CDE Y
FGH Y
IJK Y
LMN Y
OPQ Y
QRS Y
and the list goes on. Example if I wanted to change the entire status from Y to N, the query would be similar to this.
update database
set status = 'N'
However if I want to add numerous values, I'm not sure how to query it out.
update database
set status = 'N'
where (username != 'ABC' or username != 'DEF')
would be great if someone could teach and explain step by step cause I can't seem to understand how people use specific functions such as t1 and t2 to solve this and group by as well.
Like NoDisplayName mentions in the latter part of his comment,
Use of NOT IN is your WHERE clause is the one required to exclude mutliple values. Like this :
update database
set status = 'N'
where username NOT IN ('ABC', 'CDE', 'XYZ')
If the values are to be drawn from a table/recordset based on some criterion you can use a select query after NOT IN instead of a list of values.

Oracle SQL How to find missing value for different users

I have 2 tables
One table with questions
ID Description
== ===========
1 Some Question
2 Some Question
3 Some Question
4 Some Question
And an other one with the awsers to each question of every users
ID_USER ID_QUESTION ANSWER
======= =========== =========
1 2 a
1 1 b
1 3 d
2 1 e
2 4 a
3 4 c
3 2 a
As you can see it is possible that a user does not answer a question and this is my problem
I am currently trying to find wich answer a user did not answer to.
I'd like to have something like this
ID_USER ID_MISSING_QUESTION
======= ===================
1 4
2 3
2 2
3 1
3 3
I can easly find the missing questions for a single user but i can't do that for every user since they are quite numerous.
Thanks Ayoye
Quick and Dirty:
SELECT TB_USER.ID, TB_QUESTION.ID AS "Q_ID" FROM TB_USER, TB_QUESTION
minus
SELECT ID_USER, ID_QUESTION FROM tb_answer
Sql Fiddle Demo here.
I think You are looking for something like this:
SELECT
u.id_user,
q.id_question
FROM
questions q
CROSS JOIN users u
LEFT JOIN answers a ON (a.id_question = q.id_question and a.id_user = u.id_user)
WHERE
a.answer IS NULL
First You shoyul create set of every question for every user, and then try to join in with Your answers. And then filer out all results that have found answers. :)
You should post the SQL statement(s) you tried, before expecting a full answer, else someone might think you want let others write all the code for you...
Nevertheless, instead of plain JOIN, use a FULL OUTER JOIN and a LEFT OUTER JOIN resp. RIGHT OUTER JOIN, depending on table ordering in your SQL statement (which you did not post yet), and filter with IS NULL.

SELECT Values in one table that don't match another table but also reference another column?

I realize that probably doesn't make sense so let me try and explain:
I have two tables with the followings columns (just relevant ones):
positTraining (positID, trainID)
empTraining (empID, trainID)
The positTraining table contains a listing of position ids along with any training ids the position requires.
The empTraining table contains a listing of employee ids along with any current training ids the employee has completed.
I want to select only the training ids required by the position that the employee has not already completed.
So, if Employee A has completed training 1 & 3 but Position X requires training 1 & 2, I want to select the trainID for the missing training (2).
I hope that makes sense.
I have searched google a million different ways and checked here on SO as well but cannot find a working answer due to this extra requirement:
I want to ONLY select the trainIDs based on the empID. Reasoning behind this is due to the fact that empID=2 may have the correct match but emp=1 may not.
The closest I've got all afternoon is by using the following:
select positID, trainID
from positTraining
except
select empID, trainID
from empTraining
Which returns:
positID | trainID
1 | 2
This is correct but only because of the current records. As soon as another employee is put in the database with the correct match this will stop working.
I have tried using several different methods:
JOINS
NOT IN
NOT EXIST
I'm sure this is way easier than I am making it but I just can't figure it out.
Thanks for any and all help, I'll be glad to add any extra details, just let me know.
EDIT 1
I'm using SQL Server 2012 Express
EDIT 2
This is what I've ended up with, I think this is going to work:
SELECT
pt.trainID AS positTrainID,
et.trainID AS empTrainID,
e.empFirst + ' ' + e.empLast AS empName
FROM
positTraining pt,
empTraining et,
emps e
WHERE
pt.positID = 1 AND
e.empID = 1 AND
pt.trainID not in (
SELECT et.trainID FROM empTraining et WHERE et.empID = 1)
AND pt.trainID = et.trainID
Result:
positTrainID empTrainID empName
2 2 Emp1
Thanks for the help!
I think this would work:
SELECT
positID, trainID
FROM
positTraining
WHERE
positID = X
AND trainID not in (
SELECT trainID FROM empTraining WHERE empID = A)
Considering X as the positionId you are looking for the Employee A

Need MDX query for total count

Last time I had posted a question which was a bit confused. But today I got the same question from my manager to get the MDX query.
Here is the scenario:
Fact Table
Ticket No / Ticket ID
1 S
2 S
3 S
3 D
4 D
Dimension Table
Ticket ID / [Count]
S 1
D 1
My manager said they are not using dimension table that they are not using just for understanding they have mentioned that. there is no use of considering it here.
So please ignore the Dimension table data.
The Output will be like this if we do group by based on Ticket ID:
Ticket ID / [Count]
S 3
D 2
If we do so we will get the total Count is
5
But I need the total count as 4 based on Ticket No.
Need help here.
Thanks in Advance.
My educated guess is that you're starting with OLAP/MDX. It's worth taking a bit of time reading in the web about MDX, something like MDX Gentle Tutorial.
Without a dimension you can not have a cube. The minimum is one dimension and one measure in your facts.
In your case
Ticket ID -> dimension with two possible values (S,D)
Ticket No -> the measure, as Aaron pointed out. use unique count as aggregation type.
The MDX would looks like :
Select
{[Ticked ID].allmembers} on 0,
{[Measures].members on 1
from [MyCube]
We could find other ways of solving this but they would be certainly slower and more complicated.