NOT IN is not working in sybase? - sql

I have two table lets say Table1 and Table2
and both table have a column Name and ID
I want to fetch all the name from Table2 which is not in Table1
I have written below query :
Select Name,ID FROM Table2 t2 WHERE t2.Name NOT IN (Select t1.Name FROM Table1 t1);
but this query is not giving expected output, I mean it also gives me Name which is in Table1.
I done some google and found it could be if Table1 have null values i.e. If sub-query result contain null. although my table doesn't have null values but for making sure this is not a problem I have rewritten query, but without ant luck:
Select Name,ID FROM Table2 t2 WHERE t2.Name
NOT IN (Select t1.Name FROM Table1 t1 where t1.Name is not null);
Still I am not getting expected result but strangely some time it gives result as expected and some time not, any suggestion, help will be appreciated.
Is there any bug in sybase 16? I am using sybase 16 with db-visualizer.
UPDATE
If I have below data
Table1
Name ID
-------------------
Jay 1
---------------------
Table2
Name ID
-------------------
Jay 1
Tom 2
---------------------
Expected result
Name ID
-------------------
Tom 2
---------------------
but I am getting :
Result coming
Name ID
-------------------
Jay 1
Tom 2
---------------------
Please note some time I am getting expected result too, not sure why some time it is working as expected and some time not

Related

How to display multiple values in on column using postgres

Given the following table structure:
table1
first | pkey <- column names
val1 | 1
table2
second | fkey <- column names
val2 | 1
val3 | 1
val4 | 1
I would like some output like the following:
first | second <- column names
val1 | val2, val3, val4
I have tried:
select table1.first, (select table2.second where table1.pkey=table2.fkey)
from table1 join on table2 where table1.pkey=table2.fkey;
Something about that looks wrong, so I get the following:
more than one row returned by a subquery used as an expression
I also tried
select table1.first, (select table2.second where table1.pkey=table2.fkey)
from table1, table2;
Try the following using string_agg. Here is the DEMO
select
first,
string_agg(second, ',') as second
from table1 t1
join table2 t2
on t1.pkey = t2.fkey
group by
first
Output
*----------------------*
| first second |
*----------------------*
| val1 val2,val3,val4 |
*----------------------*
I would recommend aggregating the second column as an array rather than a string:
select t1.first, array_agg(t2.second)
from table1 t1 join
table2 t2
on t1.pkey = t2.fkey
group by first
You are almost there. Depending on the result you want to get there are three options:
select
table1.first,
(select string_agg(table2.second, ', ') from table2 where table1.pkey=table2.fkey)
from table1;
to get a plain text value, or
select
table1.first,
(select array_agg(table2.second) from table2 where table1.pkey=table2.fkey),
array(select table2.second from table2 where table1.pkey=table2.fkey)
from table1;
to get an array of values (in two syntactic ways), or
select
table1.first,
(select json_agg(table2.second) from table2 where table1.pkey=table2.fkey)
from table1;
to get JSON array.
Note that I moved table2 completely to the subquery.
When I posted this question, I remember I had inadvertently done what was asked a while ago. But I could not remember how. Turns out this might be an easier way to do this.
select table1.first, table2 as second
from table1 join table2 on table1.pkey=table2.fkey;
Seems as though selecting the table in a join, puts the whole row of table returned in one column named the table name. Then you can use as to name the column the name you want.

SQL Server query with intersect except or union relational Algebra

I am trying to solve a problem. It seems that of a brain teaser if you ask me.
Given two tables, return only values from the first table when there is a match for EVERY record in a second table. So a record in table 1 must have a match to every record in table 2. If table 2 has fewer than every row I want to exclude it from the final result.
This must be done without using count, having, group by. I must solve it with union, intersect, except, exists.
I am using SQL Server BTW.
CREATE TABLE table1 (id int, lid int)
INSERT INTO table1 VALUES (1, 1),(1, 2),(1,3),(1,4),(2,1),(3,3),(4,4)
CREATE TABLE table2 (lid int)
INSERT INTO table2 VALUES (1),(2),(3),(4)
Table 1:
id lid
--------
1 1
1 2
1 3
1 4
2 1
3 3
4 4
Table2:
lid
-----
1
2
3
4
This method here is "not the way I am supposed to solve it". Frustrating because this solution is so simple and does exactly what it should do. I can't use count, group by, and having.
SELECT id
FROM dbo.table1, dbo.table2
WHERE table1.lid = table2.lid
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*) FROM dbo.table2)
So basically I need to find a way to exclude the results from the first table when there is not a full set of matches in table 2. In this example the only value in table 1 with a match to every record in table 2 is 1. 2,3,4 would need to be excluded.
What you're looking for has a name. It's called relational division. It has no equivalent in SQL, although it can be emulated in a variety of ways. Joe Celko has written one of the most complete blog posts about the topic.
Since you must use some of the more basic relational operators in SQL, this could be one solution for you:
SELECT DISTINCT id
FROM table1 t1a
WHERE NOT EXISTS (
SELECT *
FROM table2
WHERE NOT EXISTS (
SELECT *
FROM table1 t1b
WHERE t1a.id = t1b.id
AND t2.lid = t1b.lid
)
)
It reads in English, informally:
Get me all the elements in table1 for which there is no element in table2, which doesn't match such an element from table1
Or also:
Get me the elements from table1, which match all the elements in table2
That's one of the solutions:
select distinct id from table1 AS T1
where not exists(
select lid from table2
except
select lid from table1 where id = T1.id
)

(SQL) How to select all fields from table 1 except the id's from table 2?

I got 3 tables.
Users:
id__| login__
--------------
_1__| root
_2__| admin
_3__| user
Table 1
id__ | name__ | data_
---------------------
1____| name1__| data1
2____| name2__| data2
3____| name3__| data3
4____| name4__| data4
Table2
id__ | table1_id_| user_id
---------------------------
1____| ____3_____| ___3___
2____| ____2_____| ___3___
3____| ____2_____| ___1___
4____| ____3_____| ___1___
I want to get 'name' and 'data' from table1 except ids from table2 that belongs to users.id = 3, that means i need to get this:
Table result (all fields from table1) (result for user_id = 3) (btw for user_id = 1 result must be the same):
Desired output:
id__| name__ | data_
--------------------
1___| name1__| data1
4___| name4__| data4
---------------------
What the SQL query i should use?
Although you can solve this using NOT IN, I recommend using NOT EXISTS instead:
SELECT t1.*
FROM table1 t1
WHERE NOT EXISTS (SELECT 1
FROM table_2 t2
WHERE t2.table1_id = t1.id AND t2.user_id = 3
);
Why? NOT IN behaves rather strangely if any table1_id value is NULL. If that occurs, then the NOT IN only returns false and NULL -- it never returns true. Hence, no rows at all will be returned if even one column value is NULL.
NOT EXISTS, on the other hand, behaves more intuitively, so you don't have to worry about this condition.
If I understood correctly this should is what you want:
SELECT * FROM table1 WHERE id NOT IN (SELECT table1_id FROM table2 WHERE user_id = 3);

Comparing two tables and get the values that dont match

I have two tables with articles.
table 1 article and table 2 articlefm
both tables have one field with artnr.
'table 1' has 2192 artnr and 'table 2' has 2195 artnr.
I want in my query to find out whats the artnr of the 3 articles that is not matched.
If 'table 2' has more articles then 'table 1' then I need a list with those artnr.
How can I make this?
You can do this using a FULL JOIN:
SELECT COALESCE(t1.Artnr, t2.Artnr) AS Artnr,
CASE WHEN t1.Artnr IS NULL THEN 'Table1' ELSE 'Table2' END AS MissingFrom
FROM Table1 AS t1
FULL JOIN Table2 AS t2
ON t1.Artnr = t2.Artnr
WHERE t1.Artnr IS NULL
OR t2.Artnr IS NULL;
Note, that just because there is a difference in the count of 3, it does not necessarily mean that there are only 3 records in one table missing from the other. Imagine the following:
Table1 Table2
------ -------
1 2
2 4
3 6
4
The difference in count is 1, but there are actually 2 records present in table1 that aren't in table2, and 1 in table2 that isn't in table1. Using the above full join method you would get a result like:
Artnr | MissingFrom
------+-------------
1 | Table1
3 | Table1
6 | Table2
In most databases you can use except (SQL standard) or minus (Oracle specific):
select artnr
from articlefm -- table 2
except
select artnr
from article -- table 1
Else you could try a not in:
select atrnr
from articlefm -- table 2
where atrnr not in
( select artnr
from article -- table 1
)
This will give you the article numbers that exist in 2, but not in 1.

MySQL get rows but prefer one column value over another

A bit of a strange one, I want to write a MySQL query that will get results from a table, but prefer one value of a column over another, ie
id name value prioirty
1 name1 value1 NULL
2 name1 value1 1
3 name2 value2 NULL
4 name3 value3 NULL
So here name1 has two entries, but one has a prioirty of 1. I want to get all the values from the table, but prefer the values with whatever priorty I'm after.
The results I'd be after would be
id name value prioirty
2 name1 value1 1
3 name2 value2 NULL
4 name3 value3 NULL
An equivalent way of saying it would be 'get all rows from the table, but prefer rows with a priority of x'.
This should do it:
SELECT
T1.id,
T1.name,
T1.value,
T1.priority
FROM
My_Table T1
LEFT OUTER JOIN My_Table T2 ON
T2.name = T1.name AND
T2.priority > COALESCE(T1.priority, -1)
WHERE
T2.id IS NULL
This also allows you to have multiple priority levels with the highest being the one that you want to return (if you had a 1 and 2, the 2 would be returned).
I will also say though that it does seem like there are some design problems in the DB. My approach would have been:
My_Table (id, name)
My_Values (id, priority, value)
with an FK on id to id. PKs on id in My_Table and id, priority in My_Values. Of course, I'd use appropriate table names too.
You need to redesign your table first.
It should be:
YourTable (Id, Name, Value)
YourTablePriority (PriorityId, Priority, Id)
Update:
select * from YourTable a
where a.Id not in
(select b.Id from YourTablePriority b)
This should work in sql server, you may need a little change to make it work in mysql.
Maybe something like:
SELECT id, name, value, priority FROM
table_name GROUP BY name ORDER BY priority
Although not having a database in front of me I can't test it...
If I understand correctly, you want the value of a name given a specific priority, or the value associated with a NULL priority. (You do not necessarily want the MAX(priority) that exists.)
Yes, you've got some awkward design issues which you should address, but let's solve the problem you do have at present (and you can later migrate to the problem you ought to have :) ):
mysql> SET #priority = 1; -- the priority we want, if recorded
mysql> PREPARE stmt FROM "
SELECT
t0.*
FROM
t t0
LEFT JOIN
(SELECT DISTINCT name, priority FROM t WHERE priority = ?) t1
ON t0.name = t1.name
WHERE
t0.priority = t1.priority
OR
t1.priority IS NULL
";
mysql> EXECUTE stmt USING #priority;
+----+-------+--------+----------+
| id | name | value | priority |
+----+-------+--------+----------+
| 2 | name1 | valueX | 1 |
| 3 | name2 | value2 | NULL |
| 4 | name3 | value3 | NULL |
+----+-------+--------+----------+
3 rows in set (0.00 sec)
(Note that I changed the prioritized value of "name1" to "valueX" in the above -- your original formulation had identical value values for "name1" regardless of priority, which made it hard for me to understand why you cared to discriminate one from the other.)