find difference between two tables in sql - sql

what is the equivalent sql of this table? i want to get only the names of the persons from all_user table who are not in your_friend table
Angelina Jolie
Brad Pitt
Peter Parker
Clark Kent
table name: all_user
(users)
Angelina Jolie
Brad Pitt
Peter Parker
Mary Jane
Clark Kent
Lois Lane
table name: your_friend
(friend)
Lois Lane
Marj Jane
select distinct * from all_user where not in (select * from your_friend where all_user.users = your_friend.friend)
This is my answer and i am getting an error near IN syntax.

You haven't specified a RDBMS. If your engine supports it the EXCEPT operation is what you are looking for. It evaluates the output of two query expressions and returns the difference between the results. The result set contains all rows returned from the first query expression except those rows that are also returned from the second query expression.
SELECT DISTINCT <Columns_To_Be_Included>
FROM all_user
EXCEPT
SELECT DISTINCT <Columns_To_Be_Included>
FROM your_friend
But be careful that this works at the record level. So, you have to only specify the columns that you want to include in the comparison.

Try this
select distinct * from all_users where users not in (select distinct friend from your_friend)

Related

Query rows and include rows with columns reversed

I'm trying to query a table. I want the results to include the FROM and TO columns, but then also include rows with these two values reversed. And then I want to eliminate all duplicates. (A duplicate is the same two cities in the same order.)
For example, given this data.
Trips
FROM TO
-------------------- --------------------
West Jordan Taylorsville
Salt Lake City Ogden
West Jordan Taylorsville
Sandy South Jordan
Taylorsville West Jordan
I would want the following results.
West Jordan Taylorsville
Taylorsville West Jordan
Salt Lake City Ogden
Ogden Salt Lake City
Sandy South Jordan
South Jordan Sandy
I want to do this using C# and Entity Framework, but I could use raw SQL if I need to.
Is it possible to do this in a query, or do I need to manually perform some of this logic?
Not sure if I'm following, but doesn't just a simple union work for your sample?
select from, to
from some_table
union
select to, from
from some_table
I do believe the first sub query should handle the first part of your question. the WHERE ID NOT IN will handle the second part of your question.
SELECT *
FROM
(
SELECT *
FROM Trips
WHERE ID IN (
SELECT ID
FROM Trips t1
INNER JOIN Trips AS t2
ON t2.To = t1.From AND t2.From = t1.To
)
)
WHERE ID NOT IN
(
SELECT MIN(ID)
FROM Trips
GROUP BY [From], [To]
)
I am assuming there is more to the table than just those fields. Usually you have a field (primary key) to uniquely identify the row. I am using ID for that field, replace with whatever your table is using.

Combining two mostly identical rows in SQL

I have a table that contains data like below:
Name
ID
Dept
Joe
1001
Accounting
Joe
1001
Marketing
Mary
1003
Administration
Mary
1009
Accounting
Each row is uniquely identified with a combo of Name and ID. I want the resulting table to combine rows that have same Name and ID and put their dept's together separated by a comma in alpha order. So the result would be:
Name
ID
Dept
Joe
1001
Accounting, Marketing
Mary
1003
Administration
Mary
1009
Accounting
I am not sure how to approach this. So far I have this, which doesn't really do what I need:
SELECT Name, ID, COUNT(*)
FROM employees
GROUP BY Name, ID
I know COUNT(*) is irrelevant here, but I am not sure what to do. Any help is appreciated! By the way, I am using PostgreSQL and I am new to the language.
Apparently there is an aggregate function for string concatenation with PostgreSQL. Find documentation here. Try the following:
SELECT Name, ID, string_agg(Dept, ', ' ORDER BY Dept ASC) AS Departments
FROM employees
GROUP BY Name, ID

Joining tables without keys causes incorrect results

I have 2 tables - one master and the other lookup. both don't have any keys. The structure of the tables is below.
first name last name role location Compensation Level state
john smith Manager LA A CA
john smith Manager BOS B MA
super smither developer LA B CA
tina taylor supervisor SFO A CA
tina taylor supervisor BOS B MA
first name last name role dept
john smith manager finance
john smith manager hr
super smither developer PA
tina taylor supervisor HR
tina taylor supervisor hr
very understandably, joining the two tables to get the dept for a first name, last name and role combination will result in incorrect results since there are other fields involved in the mix which identify a true unique record.
But given a structure like this, is there any way i can join the two tables to get the dept?
Using an inline subquery is not an option due to the way the final procedure is designed and due to other factors.
Any thoughts on this?
Expected output:
first name last name role location Compensation state dept
john smith Manager LA A CA finance
john smith Manager BOS B MA hr
super smither developer LA B CA PA
tina taylor supervisor SFO A CA HR
tina taylor supervisor BOS B MA HR
Here's an example that gives deterministic results, but they're arbitrary results. It's simply bases on determining an "ordered position" in each table, so that a choice can be made, and that choice be the same every time the query is executed, but there is no way to know that the choice is the correct one.
WITH
sorted_t1 AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY first_name, last_name, role
ORDER BY compensation_level, location, state) AS discriminator
FROM
t1
)
,
sorted_t2 AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY first_name, last_name, role
ORDER BY dept) AS discriminator
FROM
t2
)
SELECT
*
FROM
sorted_t1 t1
FULL OUTER JOIN
sorted_t2 t2
ON t1.first_name = t2.first_name
AND t1.last_name = t2.last_name
AND t1.role = t2.role
AND t1.discriminator = t2.discriminator
NOTES:
This assumes a "case-insensitive" collation sequence. Otherwise the john smith rows will never join (as 'Manager' wouldn't match 'manager')
Similarly, the two tina taylor rows in table 2 are different ('hr' vs 'HR'), but if the collation sequence is case-insensitive it doesn't matter which gets joined to which, as there is no "material" difference between the rows.
It's also worth noting that in the example above there is no Real Reason to assume that the 'John Smith' from LA is in finance. The query simply forces that association because or the ORDER BY chosen in the ROW_NUMBER(). This means that when using this technique you really should be using other fields, one's that mean something in relation to each other.

SQL: How to select and add the second column below the first column to create a one column

I have a table: tblperson
There are two columns in tblperson:
person1 person2
Anna Sarah
Louis Mike
Kisha
I want to add the second column (person2) below the first column (person1) to create only one column (persons)
persons
Anna
Louis
Kisha
Sarah
Mike
I've tried using UNION but it would make my query large especially when there are more than two columns involved
Can anyone give hints to query for generating these records?
Thank you
You would do this using union all, but also with order by:
select person
from (select person1 as person, 1 as which from tblperson union all
select person2 as person, 2 from tblperson
) p
order by which;
The order by is pretty important. It is true that you can simply do:
select person1 as person from tblperson union all
select person2 as person from tblperson
However, I consider this a little dangerous, because SQL standards do not guarantee that the first subquery is executed before the second. In practice, SQL Server does execute these in order, but there is no ongoing guarantee.

Distinct ordering not in place

I have a temporary table making a list of names which are ordered by a different column, e.g.
#table:
John, 1
Mary, 3
Mary, 5
Mary, 7
John, 8
Kyle, 9
Brad, 10
when I call a simple select * from #table, that's what I get, but when I call a select distinct name from #table I get this:
Kyle
John
Mary
Brad
Why is it not using in-place ordering? Is this a sql quirk I don't know about? I would expect (and want) it to be:
John
Mary
Kyle
Brad
EDIT: Additional Question: Since I 'Ordered By' on the original table, is there a functional reason why it wouldn't persist?
When using SELECT DISTINCT you can't order by a column that's not being selected. The easiest way to do what you want is:
SELECT name FROM #table GROUP BY name ORDER BY min(id);