duplicate answers when predicate in more than one field SQL - sql

I'm so new to this that even the answers on questions similar to my one really don't make any sense to me (I started SQL last week)
I'm trying to list addresses from Table 1 where there are multiple in each address with the same first and surnames (i.e. John Smith and John Smith). I have first names and surnames in separate fields.
I tried
SELECT *
FROM addresses
WHERE EXISTS (
SELECT individuals.FirstName
AND individuals.Surname
FROM individuals
WHERE addresses.AddressID = individuals.AddressID
GROUP BY addresses.StreetName
HAVING COUNT( * ) >1`
but this just gives me a list of every address that has more than one person in it..
Can anyone give me a (simpleish) answer that I might get my head around.
Thanks, Stacey

If you add
individuals.FirstName, individuals.Surname
after
GROUP BY addresses.StreetName
then that should do what you want.

SELECT addresses.*
FROM addresses
INNER JOIN
(
SELECT AddressID
FROM individuals
GROUP BY AddressID, FirstName, Surname
HAVING COUNT(*) > 1
) as tbl1
ON tbl1.AddressID = addresses.AddressID

How about:
SELECT
a.*
FROM
addresses a
JOIN
individuals i
ON a.AddressID = i.AddressID
GROUP BY
a.StreetName, i.FirstName, i.Surname
HAVING
COUNT(1) > 1

Related

How to write a Sql query for retrieving one row from duplicate rows?

i have a User table which has many users but some users are having same first name and Last Name but only one user will have status active . So my requirement is if the user is unique i need the user regardless of Status but if the user is duplicate i need the record having status active.
How can i achieve this in SQL server?
Sorry For the confusion here is the example of User table
my result table should be
Here Steve Jordan is having 2 records so i need the record having status 1
and for records having distinct First name and last name i need all the records regard less of status.
Note : I have a user id as primary key but i am joining on first name and last name because other table doesn't have user id.
SELECT UserId, FirstName, LastName, Status FROM (
SELECT *
, ROW_NUMBER() OVER (PARTITION BY FirstName, LastName
ORDER BY Status DESC) AS rowNum
FROM [User]
) u
WHERE u.rowNum = 1
This essentially groups by first and last name, orders by Status so that active are higher priority, and takes only one of each unique first/last name combination. This ensures that each each unique first/last name combination is in the result set only once, and if there are multiples, the active one is the one returned. If a name combination has multiples, but they are all not active, then only one is returned, chosen arbitrarily.
Ideally, you should have the User ID PK in both tables, as this is much stronger relationally.
EDIT: A bit more complex, but this should give you what you're looking for.
SELECT *
FROM YourOtherTable A
JOIN Users B
ON A.FirstName = B.FirstName AND A.FirstName = B.FirstName
LEFT JOIN
(
SELECT FirstName, LastName FROM User GROUP BY FirstName, LastName HAVING COUNT(FirstName) = 1
) C
ON B.FirstName = C.FirstName AND B.LastName = C.LastName
WHERE B.Status = 1 OR C.FirstName IS NOT NULL
I didn't get you question. But, as per your subject line. It seems like you want the record, which is active, if record is duplicate.
select T.* from yourTable T INNER JOIN (select user, count(*) cnt FROM yourTable GROUP BY user) A ON A.user=T.user
WHERE A.cnt>1 and T.status='A';
If it wasn't your requirement. Then, I would ask you to share your table structure and expected output to understand better.

sql query to select matching rows for all or nothing criteria

I have a table of cars where each car belongs to a company. In another table I have a list of company locations by city.
I want to select all cars from the cars table whose company has locations on all cities passed into the stored procedure, otherwise exclude those cars all together even if it falls short of one city.
So, I've tried something like:
select id, cartype from cars where companyid in
(
select id from locations where cityid in
(
select id from cities
)
)
This doesn't work as it obviously satisfies the condition if ANY of the cities are in the list, not all of them.
It sounds like a group by count, but can't make it work with what I tried.
I"m using MS SQL 2005
One example:
select id, cartype from cars c
where ( select count(1) from cities where id in (...))
= ( select count(distinct cityid)
from locations
where c.companyid = locations.id and cityid in (...) )
Maybe try counting all the cities, and then select the car if the company has the same number of distinct location cities are there are total cities.
SELECT id, cartype FROM cars
WHERE
--Subquery to find the number of locations belonging to car's company
(SELECT count(distinct cities.id) FROM cities
INNER JOIN locations on locations.cityid = cities.id
WHERE locations.companyId = cars.companyId)
=
--Subquery to find the total number of locations
(SELECT count(distinct cities.id) FROM cities)
I haven't tested this, and it may not be the most efficient query, but I think this might work.
Try this
SELECT e.*
FROM cars e
WHERE NOT EXISTS (
SELECT 1
FROM Cities p
WHERE p.location = e.Location
)

How to fetch the non matching rows in Oracle

Can anyone help me fetch the non matching rows from two tables in Oracle?
Table: Names
Class_id Stud_name
S001 JAMES
S001 PETER
S002 MARK
Table: Course
Course_id Stud_name
S001 JAMES
S001 KEITH
S002 MARK
Output
I need the rows to display as
CLASS ID STUD_NAME_FROM_NAME_TABLE STUD_NAME_FROM_COURSE_TABLE
---------------------------------------------------------------------
S001 PETER KEITH
I have used Oracle joins to fetch the non matching names:
SELECT *
FROM Names, Course
WHERE Names.Class_id=Course.Course_id
AND Names.Stud_name<>Course.Stud_name
This query is returning duplicate rows.
If you insist on Join you can use this one:
SELECT *
FROM Names
FULL OUTER JOIN Course ON Names.Class_id=Course.Course_id
AND Names.Stud_name = Course.Stud_name
WHERE Names.Stud_name IS NULL or Course.Stud_name IS NULL
Fetches unmatched rows in Names table
SELECT * FROM Names
WHERE
NOT EXISTS
(SELECT 'x' from Course
WHERE
Names.Class_id = Course.Course_id AND
Names.Stud_name = Course.Stud_name)
Fetches unmatched rows in Names and Course too!
SELECT Names.Class_id,Names.Stud_name,C1.Stud_name
FROM Names , Course C1
WHERE Names.Class_id = C1.Course_id AND
NOT EXISTS
(SELECT 'x' from Course C2
WHERE
Names.Class_id = C2.Course_id AND
Names.Stud_name = C2.Stud_name);
When you ask for unmatching rows I assume that you want rows that exist in names but not in course.
If this is the case you're probably after
select * from names
where (class_id, stud_name ) not in
(select course_id, stud_name from course);
Your query returned duplicate rows beacuse for each row in names it selected all rows in course that satisfied the where condition.
So, for the row S001, PETER in names it faound that S001, JAMES and S001, KEITH matched that condition, thus, that row was "returned" twice.
EDIT Since it is not clear if stud_name is a primary key, or unique (and on second sight I think it's not), you'd probably want a
select * from names
where not exists (
select 1 from course where
names.class_id = course.course_id and
names.stud_name <> course.stud_name
)
Edit II if you insist on using a join (as per your comment) you might want to try a
select distinct names.* from...
Hope it helps you
with not_in_class as
(select a.*
from Names a
where not exists ( select 'x'
from course b
where b.Course_id = a.class_id
and a.Stud_name = b.Stud_name)),
not_in_course as
(select b.*
from course b
where not exists ( select 'x'
from Names a
where b.Course_id = a.class_id
and a.Stud_name = b.Stud_name))
select x.class_id,
x.Stud_name NOT_IN_CLASS,
y.stud_name NOT_IN_COURSE
from not_in_class x, not_in_course y
where x.class_id = y.course_id
Output
| CLASS_ID | NOT_IN_CLASS | NOT_IN_COURSE |
|----------|--------------|---------------|
| S001 | PETER | KEITH |
Only problem is that if multiple mismatches are there in both the tables for a given id, it works for single mismatch for a particular id. You need to rework if multiple mismatches are there for the same id.
Well, I am not sure if I understand correctly what you are asking. I think you want a list of all IDs where the student list in class table and course table differs. Then you want to show the id and the students that are in class but not in course and the students that are in course but not in class.
To do so you would full outer join the tables. That gives you students that are both in class and course, students that are in class and not in course, and students that are in course and not in class. Filter your results where either class_id or course_id is null then to get the students missing in course or class. At last group by id and list the students.
select coalesce(class.class_id, course.course_id) as id
, listagg(class.stud_name, ',') within group (order by class.stud_name) as missing_in_course
, listagg(course.stud_name, ',') within group (order by course.stud_name) as missing_in_class
from class
full outer join course
on (class.class_id = course.course_id and class.stud_name = course.stud_name)
where class.class_id is null or course.course_id is null
group by coalesce(class.class_id, course.course_id);
Here is the SQL fiddle showing how it works: http://sqlfiddle.com/#!4/8aaaa/2
EDIT: In Oracle 9i there is no listagg. You can use the inofficial function wm_concat instead:
select coalesce(class.class_id, course.course_id) as id
, wm_concat(class.stud_name) as missing_in_course
, wm_concat(course.stud_name) as missing_in_class
from class
full outer join course
on (class.class_id = course.course_id and class.stud_name = course.stud_name)
where class.class_id is null or course.course_id is null
group by coalesce(class.class_id, course.course_id);

Creating table using select statement from multiple tables

I have this university task to create table using SELECT statement from multiple tables, but it's not as simple... here's basic info:
I'm using 2 tables -
CITY(city_ID, name);
PERSON(person_ID, name, surname, city_ID);
--city_ID is FK indicating in which city person was born.
Now my task is to create new table
STATISTICS(city_ID, city_name, number_of_births);
--number_of_births is basically a count of people born in each city
Problem is that I have to use only SELECT statement to do so.
I've tried something like this: (I'm well aware that this cannot possibly work but as to give you a better idea where I'm stuck)
CREATE TABLE Statistics AS
(SELECT city.city_ID, city.name as "city_name", number_of_births AS
(SELECT COUNT(*) FROM person WHERE person.city_id = city.city_id)
FROM city, person);
For SQL Server you can do SELECT * INTO. Something like this:
SELECT
*
INTO Statistics
FROM (
SELECT
city.city_ID,
city.name as "city_name",
(SELECT COUNT(*) FROM person WHERE person.city_id = city.city_id) as 'number_of_births'
FROM city
inner join person on city.city_id = person.city_id
) t1
(Posted on behalf of the question author).
Ok, this got really messy. Dave Zych's answer was correct when rewritten in Oracle dialect.
CREATE TABLE Statistics AS SELECT * FROM (
SELECT DISTINCT
city.city_ID,
city.name AS "City_name",
(SELECT COUNT(*) FROM person WHERE person.city_ID = city.city_ID) AS "number_of_births"
FROM city INNER JOIN person ON city.city_ID = person.city_ID);

SQL query for finding row with same column values that was created most recently

If I have three columns in my MySQL table people, say id, name, created where name is a string and created is a timestamp.. what's the appropriate query for a scenario where I have 10 rows and each row has a record with a name. The names could have a unique id, but a similar name none the less. So you can have three Bob's, two Mary's, one Jack and 4 Phil's.
There is also a hobbies table with the columns id, hobby, person_id.
Basically I want a query that will do the following:
Return all of the people with zero hobbies, but only check by the latest distinct person created, if that makes sense. Meaning if there is a Bob person that was created yesterday, and one created today.. I only want to know if the Bob created today has zero hobbies. The one from yesterday is no longer relevant.
select pp.id
from people pp, (select name, max(created) from people group by name) p
where pp.name = p.name
and pp.created = p.created
and id not in ( select person_id from hobbies )
SELECT latest_person.* FROM (
SELECT p1.* FROM people p1
WHERE NOT EXISTS (
SELECT * FROM people p2
WHERE p1.name = p2.name AND p1.created < p2.created
)
) AS latest_person
LEFT OUTER JOIN hobbies h ON h.person_id = latest_person.id
WHERE h.id IS NULL;
Try This:
Select *
From people p
Where timeStamp =
(Select Max(timestamp)
From people
Where name = p.Name
And not exists
(Select * From hobbies
Where person_id = p.id))