select rows from a database table with common field in sqlite - sql

i have a table as follows:
create table table1(id integer,firstname text,lastname text);
firstname lastname======== =========
1 ben taylor
2 rob taylor
3 rob smith
4 rob zombie
5 peter smith
6 ben smith
7 peter taylor
I want to select rows with a lastname , where the lastname must be shared by ben and rob and firstnames must be ben and rob.
Hence in the above table the result of the select query must be:
1 ben taylor
2 rob taylor
3 rob smith
6 ben smith
what must be the sql query to get the above results?
I tried - select * from table1 as a,table1 as b where a.firstname='ben' and b.firstname='rob' and a.lastname=b.lastname this joined all the resultant rows which is not what i inteneded.

You can use two filtering joins to demand that the lastname is shared with both a Ben and a Rob:
select *
from Table1 t1
join Table1 rob
on rob.firstname = 'rob'
and t1.lastname = rob.lastname
join Table1 ben
on ben.firstname = 'ben'
and t1.lastname = ben.lastname
where t1.firstname in ('ben', 'rob')
Live example at SQL Fiddle.

select *
from table1 where first_name = 'ben' or first_name = 'rob'
and last_name
in (select last_name from table1 where first_name = 'rob' and last_name
in (select last_name from table1 where first_name = 'ben'))

Related

Changing record values based on whether there are duplicates when two tables are combined

I know I can join Table #1 and Table #2 with a UNION and then filter out duplicate Id's using DISTINCT. However, for the duplicate contacts I'd like to change DrinkPreference to Coke/Pepsi.
Is this possible?
Starting Table #1
Id
FirstName
LastName
DrinkPreference
123
Tom
Bannon
Pepsi
124
Sarah
Smith
Pepsi
Starting Table #2
id
FirstName
LastName
DrinkPreference
125
Jim
Henry
Coke
123
Tom
Bannon
Coke
Table? #3 - combined with DrinkPreference set to Coke/Pepsi where contact exists in both tables?
Id
FirstName
LastName
DrinkPreference
125
Jim
Henry
Coke
123
Tom
Bannon
Coke/Pepsi
124
Sarah
Smith
Pepsi
You can try this one
SELECT coalesce(t1.firstname, t2.firstname) AS firstname,coalesce(t1.lastname,t2.lastname) AS lastname, CASE WHEN t1.drinkpreferences IS NULL THEN t2.drinkpreferences WHEN t2.drinkpreferences IS NULL THEN t1.drinkpreferences
ELSE t1.drinkpreferences || '/' || t2.drinkpreferences END AS drinkpreferences FROM table1 t1 FULL JOIN table2 t2 ON t1.id = t2.id
Achievable using multiple unions and joins.
select distinct FirstName, LastName, case when ct = 2 then 'Coke/Pepsi' else DrinkPreference end
from (
select FirstName, LastName, DrinkPreference, Id from table1
union all
select FirstName, LastName, DrinkPreference, Id from table2) a
left join
(
select count(1)ct, Id from
(select Id from table1
union all
select Id from table2) t1
group by Id
) b on b.Id = a.Id

Filtering SQL rows based on values from other rows

Using a SQL Server 2016 SP1 database I have this data in table name AgentsTable:
SELECT * FROM AgentsTable;
user_id first_name last_name agent_id agent_status agent_code
2003015038088 John Brown 22307 Retired 12345
2003015038088 John Brown 22307 Death 12399
4432442556456 Mary Jane 24667 Active 32133
7746234737464 Harry Smith 29981 Retired 42354
3455555657677 Mark Aguy 29654 Active 34655
5436546674465 Sally Sam 22584 Retired 45464
The second row shows that 'John Brown' is dead (agent_status = 'Death'), so I would like to exclude all rows for that agent_id who is dead. (Note that John Brown has two different agent_codes, so there's one row for each agent_code. That's how the source data is...)
This query:
SELECT * FROM AgentsTable WHERE agent_status = 'Retired';
Will return this:
user_id first_name last_name agent_id agent_status agent_code
2003015038088 John Brown 22307 Retired 12345
7746234737464 Harry Smith 29981 Retired 42354
5436546674465 Sally Sam 22584 Retired 45464
The result I want, where John Brown (22307) is excluded, is:
user_id first_name last_name agent_id agent_status agent_code
7746234737464 Harry Smith 29981 Retired 42354
5436546674465 Sally Sam 22584 Retired 45464
How can I achieve that? In other words, how can I exclude one row based on a value in another related row?
You can use CTE and get agents who are not deceased as given below:
;WITH CTE_deceasedagents AS
(
SELECT agent_id
FROM AgentsTable
WHERE agent_status = 'Death'
)
SELECT *
FROM AgentsTable as a
WHERE NOT EXISTS
(
SELECT agent_id
FROM CTE_deceasedagents as c
WHERE c.agent_id = a.agent_id
);
GO
SELECT * FROM AgentsTable t1 WHERE agent_status = 'Retired' where NOT EXISTS (SELECT 1 FROM AgentsTable t2 WHERE t2.agent_status = 'Death' and t2.agent_code = t1. agent_code );
I would just use not exists with a correlated subquery to ensure that no other record exists with the same user_id and a 'Death' status:
select a.*
from agentsTable a
where not exists (
select 1
from agentsTable a1
where a1.user_id = a.user_id and a1.agent_status = 'Death'
)

SQL subquery or not?

I am trying to find a query that will select from two tables but not join those two tables as I don't want the result on one line.
Lets say I have these tables:
Persons1 Persons2
Number Name Surname Number Name Surname
----------------------- -------------------------
1 Peter Miller 1 Frank Farian
2 Hans Geige 2 Thomas Müller
And when I use this query:
SELECT
NEW.NAME,
OLD.NAME
FROM
PERSONS1 NEW,
PERSONS2 OLD
WHERE
NEW.Number = 1 AND
OLD.Number = 1
I get the following result:
Peter Frank
How do I write the query to get:
Peter
Frank
Use UNION for this:
SELECT NEW.NAME
FROM PERSONS1 NEW
WHERE NEW.Number = 1
UNION
SELECT OLD.NAME
FROM PERSONS2 OLD
WHERE OLD.Number = 1

Access 2007 SQL Merge tables without creating duplicates

I would like to add the unique values of tblA to tblB without creating duplicate values based on multiple fields. In the following example, FirstName and LastName determine a duplicate, Foo and Source are irrelevant.
tblA:
FirstName LastName Foo Source
John Doe 1 A
Jane Doe 2 A
Steve Smith 3 A
Bill Johnson 2 A
tblB:
FirstName LastName Foo Source
John Doe 1 B
Bob Smith 5 B
Steve Smith 4 B
This is the result I want:
tblA:
FirstName LastName Foo Source
John Doe 1 A
Jane Doe 2 A
Steve Smith 3 A
Bill Johnson 2 A
Bob Smith 5 B
Here's an equivalent of the code I've tried:
INSERT INTO tblA
SELECT B.*
FROM tblB AS B
LEFT JOIN tblA AS A ON A.FirstName = B.FirstName AND A.LastName = B.LastName
WHERE A.FirstName IS NULL
And this is the result I get:
tblA:
FirstName LastName Foo Source
John Doe 1 A
Jane Doe 2 A
Steve Smith 3 A
Bill Johnson 2 A
John Doe 1 B
Bob Smith 5 B
Steve Smith from tblB is ignored, which is good. John Doe from tblB is added, which is bad. I've spent way too much time on this and I've inspected the data every way I can think of to ensure John Doe in tblA and tblB are the same first and last name. Any ideas on what could be going wrong?
Update: FYI, on my real tblB, about 10,000 of 30,000 should be moved to tblA. This is actually moving over 21,000. The problem is this is one step of a common process.
When I try:
SELECT tbb.*
FROM tbb
LEFT JOIN tba
ON (tbb.FirstName = tba.FirstName)
AND (tbb.LastName = tba.LastName)
WHERE (((tba.LastName) Is Null));
The only line returned is:
Bob Smith 5 B
Is it possible that John Doe has a hidden character?
Edit : Sorry, it doesn't work on Access2007
You have many way to do that :
INSERT INTO tblA
SELECT B.* FROM tblB AS B
WHERE B.firstname, B.lastname NOT IN (select firstname, lastname from tblA)
Or
INSERT INTO tblA
SELECT * FROM tblB
MINUS
SELECT * FROM tblA
This one works in Access.
You can run it to infinity - it won't add more rows than needed:
INSERT INTO tblA
SELECT B.*
FROM tblB AS B
WHERE (((B.FirstName) Not In (select firstname from tblA))
AND ((B.LastName) Not In (select firstname from tblA)))

Select query which returns exect no of rows as compare in values of sub query

I have got a table named student. I have written this query:
select * From student where sname in ('rajesh','rohit','rajesh')
In the above query it's returning me two records; one matching 'rajesh' and another matching: 'rohit'.
But i want there to be 3 records: 2 for 'rajesh' and 1 for 'rohit'.
Please provide me some solution or tell me where i am missing.
NOTE: the count of result of sub query is not fix there can be many words there some distinct and some multiple occurrence .
Thanks
Your requirements are not clear, and I'll try to explain why.
Let's define table students
ID FirstName LastName
1 John Smith
2 Mike Smith
3 Ben Bray
4 John Bray
5 John Smith
6 Bill Lynch
7 Bill Smith
Query with WHERE clause:
FirstName in ('Mike', 'Ben', 'Mike')
will return 2 rows only, because it could be rewritten as:
FirstName='Mike' or FirstName='Ben' or FirstName='Mike'
WHERE is filtering clause that just says if existing row satisfy given conditions or not (for each of rows created by FROM clause.
Let's say we have subquery that returns any number of non distinct FirstNames
In case if SQ contains 'Mike', 'Ben', 'Mike' using inner join you can get those 3 rows without problem
Select ST.* from Students ST
Inner Join (Select name from …. <your subquery>) SQ
On ST.FirstName=SQ.name
Result will be:
ID FirstName LastName
2 Mike Smith
2 Mike Smith
3 Ben Bray
Note data are not ordered by order of names returning by SQ. If you want that, SQ should return some ordering number, eg.:
Ord Name
1. Mike
2. Ben
3. Mike
In that case query should be:
Select ST.* from Students ST
Inner Join (Select ord, name from …. <your subquery>) SQ
On ST.FirstName=SQ.name
Order By SQ.ord
And result:
ID FirstName LastName
2 Mike Smith (1)
3 Ben Bray (2)
2 Mike Smith (3)
Now, let's se what will happen if subquery returns
Ord Name
1. Mike
2. Bill
3. Mike
You will end up with
ID FirstName LastName
2 Mike Smith (1)
6 Bill Lynch (2)
7 Bill Smith (2)
2 Mike Smith (3)
Even worse, if you have something like:
Ord Name
1. John
2. Bill
3. John
Result is:
ID FirstName LastName
1 John Smith (1)
4 John Bray (1)
5 John Smith (1)
6 Bill Lynch (2)
7 Bill Smith (2)
1 John Smith (3)
4 John Bray (3)
5 John Smith (3)
This is an complex situation, and you have to clarify precisely what requirement is.
If you need only one student with the same name, for each of rows in SQ, you can use something like SQL 2005+):
;With st1 as
(
Select Row_Number() over (Partition by SQ.ord Order By ID) as rowNum,
ST.ID,
ST.FirstName,
ST.LastName,
SQ.ord
from Students ST
Inner Join (Select ord, name from …. <your subquery>) SQ
On ST.FirstName=SQ.name
)
Select ID, FirstName, LastName
From st1
Where rowNum=1 -- that was missing row, added later
Order By ord
It will return (for SQ values John, Bill, John)
ID FirstName LastName
1 John Smith (1)
6 Bill Lynch (2)
1 John Smith (3)
Note, numbers (1),(2),(3) are shown to display value of ord although they are not returned by query.
If you can split the where clause in your calling code, you could perform a UNION ALL on each clause.
SELECT * FROM Student WHERE sname = 'rajesh'
UNION ALL SELECT * FROM Student WHERE sname = 'rohit'
UNION ALL SELECT * FROM Student WHERE sname = 'rajesh'
Try using a JOIN:
SELECT ...
FROM Student s
INNER JOIN (
SELECT 'rajesh' AS sname
UNION ALL
SELECT 'rohit'
UNION ALL
SELECT 'rajesh') t ON s.sname = t.sname
just because you've got a criteria in there two times doesn't mean that it will return 1 result per criteria. SQL engines usually just use the unique criteria - thus, from your example, there will be 2 criteria in IN clause: 'rajesh','rohit'
WHY do you need to return 2 results? are there two rajesh in your table? they should BOTH return then. You don't need to ask for rajesh twice for that to happen. What does your data look like? What do you want to see returned?
Hi i am query just as you give above and it give me all data that matches in the condition of in clause. just like your post
select * from person
where personid in (
'Carson','Kim','Carson'
)
order by FirstName
and its give me all records which fulfill this Criteria