How to compare two tables row by row in SQL - sql

I have two temporary tables with single column
Table 1
MaXAge (Contains maximum age of each kind)
-----------
15
15
11
Table 2
KGroup (Contains each kind)
--------------------------------------------------
Cat
Dog
Parrot
AND another Table Pets with fields
PetID Name Kind Gender Age OwnerID
NOW, I want to display name of animals with maximum age group by kind

You can do this without using any temp tables
SELECT name, age
FROM pets p
JOIN (SELECT kind, MAX(age) max_age FROM pets GROUP BY kind) AS sub ON sub.kind = p.kind AND sub.max_age = p.age

Related

How to copy information in SQL from one table to another

I need to build a query to copy information in a column from one table to a column in another table.
This is how the tables looks like:
People:
PersonId
Name
StatusId
1
John
2
Jenny
3
Steve
Assignments:
AssignmentId
Country
PersonId
1
UK.
1
2
USA
3
Status:
StateId
Name
1
Busy
2
Free
There is a relationsihp between the People and Assignments tables: PersonId on the Assignments table is a FK. The People table has a relationship with the Status table through the FK StatusId. What I need to do is populate the StatusId on the table People with the StatusId from the table Status if the person in the table People exists on the table Assignments.
On the sample above both John and Steve are in the Assignments table, in this case theirs StatusId on the table People should be set to 1.
I was trying to do it with this:
update People
set StatusId = 1
where PersonId IN (
select PersonId
from Assignments
where Assignments.PersonId = People.PersonId
)
but as you can see I am hardcoding the StatusId what will not works. Is there some way to get the StatusId based on the result of the select? Or is there another way to get the StatusId?
If you want to refer to it by "name", you can use a subquery:
update People
set StatusId = (select s.StatusId from status s where name = 'Busy')
where PersonId IN (select a.PersonId from Assignments a where a.PersonId = People.PersonId);

Selecting the amount of users that have no 'thing' assigned to it

I have a simplified table that shows my problem
Name Animal
Bill Dog
Bill Cat
Bill Fish
John Cat
John Fish
Sara Dog
Sara Cat
Mark Fish
I want the number of people that have no dog. I tried this query.
select count(distinct Name) from Table
where Animal <> 'Dog'
But it returns 4 and not the expected 2. What am I doing wrong?
Your query returned the count of names that have any animal other than dog.
select distinct name
from table t1
where not exists
(
select 1 from table t2 where t1.name=t2.name and t2.Animal='Dog'
)
Use not exists :
select count(distinct t.name) as counts
from table t
where not exists (select 1 from table where name = t.name and animal = 'Dog');
For your current query you are filtering single record based on animal name which would not produced desired result as it should be along with name column.
your where condition "Animal <> 'dog'" is filtering the rows not the names.
So try the below query
Select count(distinct Name) from Table where name not in (
select Name from Table where Animal = 'Dog')

Nested result sets as with dynamic names

I'm trying to join the result of two referencing tables to get row values which are referencing different table names, which rows are selectable by their uuid.
my tables look like this:
table entry
table map
table cats
table dogs
nrrefInt
id name mapRef breed
mapRef breed
1 123
123'dogs'
456 'bengal'
123 'sheepdog'
2 456
456 'cats'
888 'birma' 999 'poodle'
3 789
789'dogs'
4 123
refInt of entry is referencing to map. the name of map is the reference to tables in addition with the field id which is also applied on the tables cats/dogs (dynamic tables loading).
// subset 1: list of numbers that needs to be loaded from entry table (1-4)
SELECT DISTINCT refInt FROM entry WHERE nr in (1,2,3,4)
// subset 2: get all names from map that have the same id like refInt from subset1
SELECT name FROM map WHERE id in subset1
// main query: load all rows from table with the given name
// from map table that have the same mapRef value on it
SELECT * FROM (subset2.names) WHERE mapRef IN (subset2.ids)
result should be the rows:
1) 456 bengal
2) 123 sheepdog
I also made a SQLFiddle of it.
Is there a way to combine this to one query?
It's going to look something like:
SqlFiddle
select
sub.nr,
sub.breed
from (
select e.nr, e.refInt,
case
when c.breed is not null then c.breed
when d.breed is not null then d.breed
else null
end as breed
from (
select e.nr, e.refInt, m.name
from entry e
inner join map m on e.refInt = m.id
) e
left join cats c on e.refInt = c.mapRef and e.name = 'cats'
left join dogs d on e.refInt = d.mapref and e.name = 'dogs'
) sub
where sub.breed is not null
This is going to be very poor in performance.
Now the IMO the correct schema would be:
table entry
nr refint
1 123
2 456
3 789
4 124 (duplicate?)
table breed
mapRef breed species
123 sheepdog 1
999 poodle 1
456 bengal 2
888 birma 2
table species
id species
1 dogs
2 cats
This is normalized and has very good performance.
Note how the following query fully achieves the desired result set and fully demonstrates how the tables cats and dogs are truly just partitions of a single entity animals. The schema should be reworked to reflect this new understanding. This query is also efficient because the inclusion test id pushed to the depths of the innermost CTE's, at the level where actual table rows are being read, without relying on the engine to discover this potential optimization (which can be problematic with UNIONs).
with
cats2 as (
select species='cat', mapref, breed
from cats animals
join entry on entry.refint = animals.mapref
where entry.nr in (1,2,3,4)
),
dogs2 as (
select species='dog', mapref, breed
from dogs animals
join entry on entry.refint = animals.mapref
where entry.nr in (1,2,3,4)
),
animals as (
select species, mapref, breed from cats2
union all
select species, mapref, breed from dogs2
)
select species, mapref, breed
from animals
group by species, mapref, breed
This test script:
declare #entry table (nr int, refint int );
declare #map table (id int, name varchar(20) );
declare #cats table (mapRef int, breed varchar(20));
declare #dogs table (mapRef int, breed varchar(20));
insert #entry(nr,refint) values
(1,123)
,(2,456)
,(3,789)
,(4,123);
insert #map(id,name) values
(123,'dogs')
,(456,'cats')
,(789,'dogs');
insert #cats(mapRef,breed) values
(456,'bengal'),(888,'burma');
insert #dogs(mapRef,breed) values
(123,'sheepdog'), (999,'poodle');
with
cats2 as (
select species='cat', mapref, breed
from #cats animals
join #entry entry on entry.refint = animals.mapref
where entry.nr in (1,2,3,4)
),
dogs2 as (
select species='dog', mapref, breed
from #dogs animals
join #entry entry on entry.refint = animals.mapref
where entry.nr in (1,2,3,4)
),
animals as (
select species, mapref, breed from cats2
union all
select species, mapref, breed from dogs2
)
select species, mapref, breed
from animals
group by species, mapref, breed
yields as desired:
species mapref breed
------- ----------- --------------------
cat 456 bengal
dog 123 sheepdog

Linking integer id with text in Postgres

I can connect to a database in Postgres.
It has a table called country with 201 rows. This consists of two fields: country_id (integer) and country_name (text).
It has another table called school with 2233 rows. It consists of a field called country (integer). This field lists integers that each represent one of the 201 country_id from the country table.
If I do a command like:
SELECT country from school limit 10;
I can get the first 10 country_id's. Is it possible for me to easily translate these 10 country_id's into their country_name's using the country table?
You can use Join to achieve this..
I wrote the query for MYSQL
create table country
(id numeric,
c_name varchar(20));
insert into country values(1,'America');
insert into country values(2,'India');
insert into country values(3,'Britain');
insert into country values(4,'Greece');
insert into country values(5,'China');
create table School
(school_name varchar(20),
country_id Numeric);
Insert into school values ('A',2);
Insert into school values ('B',4);
Insert into school values ('c',5);
Insert into school values ('D',4);
Select c_name
from country c
join School s
on c.id = s.country_id
Order by c_name
Limit 2
c_name
China
Greece
If you only want to show the country name once you can use Distinct
Also if you are LIMIT you should do a orderby else it will give different result on each time..

Need a help o create table structure sql?

I have to create following table structure for a group.
1 member can join many groups
1 group can have only 1 owner member
need to design these two tables member and group?
i tried like
MemberTable
Mid(PK) Mname MAddress
1m aaa IND
2m bbb UK
GroupTable
Gid(PK) Mid(FK) Gname
1g 1m GROUP1
2g 1m GROUP2
3g 2m GROUP3
is this a correct approach or should i create a 3rd table?
table Member
id, memberName
table Group
id, groupName, OwnerId
with a FK from OwnerId to table member(id)
relational table MembersxGroup
memberId, groupId
with both FKs from memberId and groupId to respective tables
and a unique non clustered index covering both columns