SQL for Exclude - sql

I have a table which is a simple lists of ID numbers and NAMES - I am trying to write a SQL which only returns rows where the NAME does not have particular IDs.
This has been stumping me - the query below returns all as they have other IDs from the exclude lists (large range of IDs). How to structure a query where only those who don't have ID 2 or 3 are returned -- i.e. only returns 'bob' for table below.
select * from TABLE where ID not in (2, 3)
ID NAMES
1 bob
1 alice
2 alice
1 dave
2 dave
3 dave
4 dave
Thank you.

One method is group by and having:
select name
from t
group by name
having sum(case when ID in (2, 3) then 1 else 0 end) = 0;
If you want the original ids, you can add listagg(id, ',') within group (order by id) to the select. Or use not exists:
select t.*
from t
where not exists (select 1
from t t2
where t2.name = t.name and
t2.id in (2, 3)
);

Related

sql multiple filter all conditions in a group

I have a table with 3 fields:
id order date
1 1 null
1 2 not null
1 3 null
2 1 null
2 2 null
2 3 null
2 4 not null
3 1 null
I need the "id" in which:
ALL the "order" in (1,2,3)
and
ALL the "date" is null (so it is id 2)
I've tried as follows:
where order in (1,2,3) and date is null
but it returns both id 2 and id 1 (I'm expecting id 2 only).
Thanks for helps.
ID 3 should be also included. It satisfies your condition.
SELECT distinct id
FROM tab1 aa
WHERE aa.order IN (1, 2, 3) AND aa.data IS NULL
AND NOT exists(SELECT 1
FROM tab1 bb
WHERE ((bb.order IN (1, 2, 3) AND bb.data IS NOT NULL)
OR
(bb.order NOT IN (1, 2, 3) AND bb.data IS NULL))
AND aa.id = bb.id);
If you don't want ID 2 cause it has order in ID 4, then relax the last condition in:
bb.order NOT IN (1, 2, 3)
without the check in the date.
If with
ALL the "order" in (1,2,3)
you mean that there should be an order for 1, an order for 2 and an order for 3, then you should add and exists in the query to check this, like
and exists (select 1 form tab1 cc where aa.id = cc.id and cc.order = 1 and cc.data is not null)
and so on.
You want a result per ID, so GROUP BY it. You are only interested in order 1, 2, and 3, so use a WHERE clause. You only want IDs with all three orders and no date set. You can check this after aggregation in the HAVING clause.
select id
from mytable
where "order" in (1,2,3)
group by id
having count(*) = 3 -- all three IDs
and count("date") = 0; -- no non-null date
Rextester demo: http://rextester.com/SEE91944
(I surmise the table's unique key is id + order. Otherwise you'd have to COUNT(DISTINCT "order") and maybe to check null dates differently. As both order and date are SQL words, I am using quotes on them. You should avoid such names.)
I'm not sure what database are you using so I tried to right a query that should work with most. Have a look:
select * from
(select
id,
SUM(case
when [order] = 1 and [date] is null then 1
when [order] = 2 and [date] is null then 1
when [order] = 3 and [date] is null then 1
else 0
end) score
from test
group by id) scores
where score = 3
http://sqlfiddle.com/#!18/e4334/9
Sorry but none of above solved my question.
I solved it using "where not exists" (excluding the unwanted)
thanks to you all for your efforts.
If I've correctly interpreted your question, the following SQL does the work.
It returns id values of records for which all order who have 1, 2 or 3 value have null value for the date field:
SELECT DISTINCT id
FROM t
WHERE
order IN (1, 2, 3) AND
date IS NULL AND
id NOT IN (
SELECT id
FROM t
WHERE
order IN (1, 2, 3) AND
date IS NOT NULL
)

Sqlite query - How I can select a predecessor?

I have this table below:
ID name Last
0 Joe Doe
1 Hut Nob
2 Lis Hug
3 Edy mur
I use this query to select an ID:
SELECT name FROM myDatabase WHERE ID = 2
In this case the query returns me the string Lis, now, How I can select the predecessor value?
Simple, the predecessor from 2 is 1, so I need only to do WHERE ID < 2 or WHERE ID = 2 - 1.
But this method have a problem! Lets suppose that I delete that row (ID = 1), the query will return null, because that ID not exists.
So, in this example, how I can select the predecessor from ID 2 and return ID 0? (ID 1 is gone)
You can use subquery to find max ID that is lower than ID that you provided:
SELECT *
FROM mytable m
WHERE m.id = (SELECT MAX(m2.id)
FROM mytable m2
WHERE m2.ID < 2);
SqlFiddleDemo
Get all the smaller IDs, and from those, take only the largest one:
SELECT name
FROM MyTable
WHERE ID < 2
ORDER BY ID DESC
LIMIT 1;

Retrieve one row in select statement which generates multiple rows (by avoiding NULL rows if possible)

I want to get the Name from this table but I only have the Number which is not unique. How do I get the correct Name (please give me some SQL syntax)?
Below the database table you can see the input and expected output for
Database Table
Number Name
1 Anna
1 Anna
2 Brad
2 NULL
2 NULL
2 NULL
3 NULL
3 NULL
4 Adam
5 NULL
Input and expected output:
Number (Input) Name (Expected outpu)
1 Anna
2 Brad
3 NULL
4 Adam
5 NULL
What do I need to add to my query to make it work?
SELECT Name FROM tablename
WHERE Number='chosen number'
A simple MAX/GROUP BY will return your expected result set:
SELECT Number, MAX(Name)
FROM table name
GROUP BY 1;
Btw, NUMBER is a Reserved Name in Teradata
SELECT
number,
MAX(name)
FROM
your_table
GROUP BY
number
And/Or
SELECT
MAX(name)
FROM
your_table
WHERE
number = x
MAX, MIN, etc, all treat NULL as the last value; you only get a NULL if all values are NULL.
This is a step in the right direction, the problem is that you will still get NULL aswell if you have a row with NULL give me a bit to figure out how to filter those out if there is a name
Mysql would be this:
http://sqlfiddle.com/#!9/4beca/1
SELECT DISTINCT Name
FROM mytable
WHERE Number=1 AND Name is not null
UNION
SELECT NULL
FROM mytable
LIMIT 1
SQL-Server would be this:
http://sqlfiddle.com/#!3/f4078/11
SELECT TOP 1 sub.Name
FROM
(SELECT DISTINCT Name
FROM mytable
WHERE Number=1 AND Name is not null
UNION
SELECT NULL AS Name
FROM mytable) AS sub

How to GROUP multiple records from two different SQL statements

I have a table called tbl which contains all the data I need. I have many columns in this table, but for purposes of this example I will only list the columns necessary to accomplish this task.
Here's how data stored in the tbl (note uID is char(20) and cID is int)*:
uID cID
1 10
1 11
1 12
2 11
We usually query this table like
SELECT * FROM tbl WHERE uID = "1"
So it returns
uID cID
1 10
1 11
1 12
But I also need to return the row where uID is different but cID do match. Or grab the uID of the second row (which is 2) based on cID and do a select statement like this:
SELECT * FROM tbl WHERE uID in ('1','2')
That query will return what I'm looking for
uID cID
1 10
1 11
1 12
2 11
This table contains a lot of rows and I want to be able to do this programatically for every call where cID matches and uID is different.
Any suggestions?
I think this may be what you want:
SELECT *
FROM tbl
WHERE uID = '1'
UNION ALL
SELECT *
FROM tbl
WHERE uID <> '1' AND
EXISTS (select 1 from tbl tbl2 where tbl2.uId = '1' and tbl2.cID = tbl.cID);
or something like this:
SELECT uID, cID
FROM tbl
WHERE uID IN
(
SELECT uID
FROM tbl
INNER JOIN
(
SELECT cID
FROM tbl
GROUP BY cID
HAVING count(*) > 1
) c ON c.cID = tbl.cID
)

return IDs that have ALL of a list of correpsonding values

I have table with 2 columns ....
id id2
1 1
1 2
1 3
2 1
2 2
2 4
3 2
3 3
3 4
I want to return the ids which have for example id2 in (1, 2, 4) but that has all of the values in the list.
In this above case it would return id = 2. Is this possible?
select id
from MyTable
where id2 in (1, 2, 4)
group by id
having count(distinct id2) = 3 --this must match the number of elements in IN clause
Update:
If the list of IDs is variable, then you should create an additional table that contains the varying sets of IDs, which you can then JOIN against to do your filtering.
Are you alluding to relational division? e.g. the supplier who supplies all products, the pilot that can fly all the planes in the hanger, etc?
If so, this article has many example implementations in SQL.
Do a self-join to test different rows on the same table in one go:
SELECT id
FROM t AS t0
JOIN t AS t1 ON t1.id=t0.id
JOIN t AS t2 ON t2.id=t1.id
WHERE t0.id2=1
AND t1.id2=2
AND t2.id2=4