SQL - Accessing data in 2 tables - sql

I have two tables (table A and table B) that have a 1 to many mapping. For every record in table A, I want to check if any of its events in table B occur after 2010. For example:
Table A Table B
ID REGISTER ID DATE
A qwer A 1995-01-01
B ghlk A 1997-01-31
C thasdj A 2006-03-15
B 2001-03-15
B 2003-04-03
B 2021-08-01
B 1995-01-01
C 2001-01-01
C 2010-01-01
Therefore, the resulting Table would be
Table C
ID Register
A qwer
C thasdj
Because for ID A and C, none of their events happens after 2010.
THis is the script I tried using but I'm not sure why it's not working. Any help
SELECT *
INTO Table C
FROM Table A
where ID not in(
SELECT distinct ID from Table B
where [DATE] >= 2011-01-01

you can do it with insert into {tablename} (list column) select syntax
INSERT INTO C ( ID, Register )
SELECT A.ID, A.Register
FROM A
WHERE A.ID not in (
SELECT distinct ID from Table B
where [DATE] >= 2011-01-01
)

You can use not exists for this task. Presumably your example query is contrived however note you must properly delimit object names that contain spaces, are reserved words etc and a date value must be quoted.
select *
into TableC
from TableA a
where not exists (
select * from TableB b
where b.Id = a.Id and b.[Date] >='20110101'
);

Related

Select only those record which is either matching or not present in another table

Let's say there is a table A:
Name Class Number
A 1 50
B 2 30
C 3 20
A 1 10
And table B:
Name Class Number
A 1 50
C 3 20
Where the primary key is the Name column.
Question
I would like to keep only records in table A that match one of the following condition:
record from table A exists in table B and values are identical
record from table A does not exist in table B
Expected Result
Name Class Number
A 1 50 // kept because all values match record in table B
B 2 30 // kept because record doesn't exist in table B
C 3 20 // kept because all values match record in table B
I think that this should do it:
select a.*
from tablea a
where not exists (
select 1
from tableb b
where
a.name = b.name
and (a.class <> b.class or a.number <> b.number)
)
This phrases as: select records in table a for which no other record exists in table b with the same id and a different class or number.
Otherwise, we can also express the two conditions explicitly, like so:
select a.*
from tablea a
where
exists (
select 1
from tableb b
where a.name = b.name and a.class = b.class and a.number = b.number
)
or not exists (
select 1 from tableb b where a.name = b.name
)

Value present in more than one table

I have 3 tables. All of them have a column - id. I want to find if there is any value that is common across the tables. Assuming that the tables are named a.b and c, if id value 3 is present is a and b, there is a problem. The query can/should exit at the first such occurrence. There is no need to probe further. What I have now is something like
( select id from a intersect select id from b )
union
( select id from b intersect select id from c )
union
( select id from a intersect select id from c )
Obviously, this is not very efficient. Database is PostgreSQL, version 9.0
id is not unique in the individual tables. It is OK to have duplicates in the same table. But if a value is present in just 2 of the 3 tables, that also needs to be flagged and there is no need to check for existence in he third table, or check if there are more such values. One value, present in more than one table, and I can stop.
Although id is not unique within any given table, it should be unique across the tables; a union of distinct id should be unique, so:
select id from (
select distinct id from a
union all
select distinct id from b
union all
select distinct id from c) x
group by id
having count(*) > 1
Note the use of union all, which preserves duplicates (plain union removes duplicates).
I would suggest a simple join:
select a.id
from a join
b
on a.id = b.id join
c
on a.id = c.id
limit 1;
If you have a query that uses union or group by (or order by, but that is not relevant here), then you need to process all the data before returning a single row. A join can start returning rows as soon as the first values are found.
An alternative, but similar method is:
select a.id
from a
where exists (select 1 from b where a.id = b.id) and
exists (select 1 from c where a.id = c.id);
If a is the smallest table and id is indexes in b and c, then this could be quite fast.
Try this
select id from
(
select distinct id, 1 as t from a
union all
select distinct id, 2 as t from b
union all
select distinct id, 3 as t from c
) as t
group by id having count(t)=3
It is OK to have duplicates in the same table.
The query can/should exit at the first such occurrence.
SELECT 'OMG!' AS danger_bill_robinson
WHERE EXISTS (SELECT 1
FROM a,b,c -- maybe there is a place for old-style joins ...
WHERE a.id = b.id
OR a.id = c.id
OR c.id = b.id
);
Update: it appears the optimiser does not like carthesian joins with 3 OR conditions. The below query is a bit faster:
SELECT 'WTF!' AS danger_bill_robinson
WHERE exists (select 1 from a JOIN b USING (id))
OR exists (select 1 from a JOIN c USING (id))
OR exists (select 1 from c JOIN b USING (id))
;

Union all and merge in sql

Here is what I needed:
I have:
Table A PT*,NAME,AGE
Table B PT*,COURSE,RESULT
Table C PT*,COURSE,RESULT,RANk
Wondering how could I UNION Table B and Table C and later Merge with Table A to get the output as below(Table D). PT is the PKey among all.
PT NAME AGE COURSE RESULT RANK
100 SLK 29 Test1 29 - result of merge between Table A and Table B
200 AAR 30 Test2 23 10 - result of merge between Table A and Table C
To get desirable output just perform a simple SQL SELECT query:
SELECT A.PT, A.NAME, A.AGE, B.COURSE, B.RESULT, C.RANK
FROM
A join B on A.PT=B.PT
join C ON A.PT = C.PT
Why you need COURSE, RESULT fields in table C, by the way, as they are already stored in table B?

Combining sql select and Count

I have two tables
A and B
A B
----------------- -----------------
a_pk (int) b_pk (int)
a_name(varchar) a_pk (int)
b_name (varchar)
I could write a query
SELECT a.a_name, b.b_name
FROM a LEFT OUTER JOIN b ON a.a_pk = b.a_pk
and this would return me a non distinct list of everything in table a and its table b joined data. Duplicates would display for column a where different b records shared a common a_pk column value.
But what I want to do is get a full list of values from table A column a_name and ADD a column that is a COUNT of the joined values of table B.
So if a_pk = 1 and a_name = test and in table b there are 5 records that have a a_pk value of 1 my result set would be
a_name b_count
------ -------
test 5
The query should like this :
SELECT
a.a_name,
(
SELECT Count(b.b_pk)
FROM b
Where b.a_pk = a.a_pk
) as b_count
FROM a
SELECT a_name, COUNT(*) as 'b_count'
FROM
A a
JOIN B b
ON a.a_pk = b.a_pk
GROUP BY a_name
SELECT
a.name,
(
SELECT COUNT(1)
FROM B b
WHERE b.a_pk = a.a_pk
)
FROM A a

Subtraction between two queries

Let's say I have 2 database tables:
table B is a set of people, table A is a set of people from table B
Table A = (no, id, date) no is PK, id refer to table B
Table B = (id, name) id is PK
My goal is to get data of people (id and name) who didn't attend on a given date (like today for example) the theory seems simple, set of B substract by set of A who attend (in today) but how can I do this in SQL query? I think about first query substracted by second query but got confused.
select * from b where
not exists (select no from A where A.id=B.id and date=#yourdate)
If I understood properly it would be something like this:
select b.id, b.name from tableB b where b.id not in (
select b.id from tableA a
inner join tableB b on a.id = p.id
where a.date = CURRENT_DATE)