Select between multiple lines - sql

I have this situation:
I need to select data from tableA where its foreign key refers to tableB
like: tableA.tableB_id = tableB id informed
OR
the second restriction refers to postal code informed on tableB, there is initial postal code and final postal code in tableB, and a single postal code on tableA.
Example:
CREATE TABLE tableA (
id integer PRIMARY KEY,
tableB_id INTEGER,
postalCode varchar(10)
);
CREATE TABLE tableB (
id integer PRIMARY KEY,
InitialPostalCode varchar(10),
FinalPostalCode varchar(10)
);
Table B is a LIST of locations with multiple initial and final postal codes
I need to select from tableA where tableB_id = tableB.id OR tableA.cep is between tableB.InitialPostalCode and tableB.FinalPostalCode
SELECT
id,
postalCode
FROM
tableA
WHERE
tableB_id = ID
OR postalCode BETWEEN...
SELECT
InitialPostalCode,
FinalPostalCode
FROM
tableB
WHERE
id = some ID;
how can I merge these two queries?
thanks everyone!

Is this what you want?
SELECT a.id, a.postalCode
FROM tableA a
WHERE EXISTS (SELECT 1 FROM tableB b WHERE b.id = a.tableB_id) OR
EXISTS (SELECT 1 FROM tableB b WHERE a.cep BETWEEN b.InitialPostalCode AND b.FinalPostalCode);
I prefer to use EXISTS because:
You only want columns from tableA, so tableB does not need to be in the FROM clause.
Each subquery can be optimized with appropriate indexes.
There is no reason to remove duplicates after the processing.
OR in ON clauses can be very inefficient.

Related

SQL SELECT and check column from second table

I have two tables in my database. From the Table B i collect some data. I include by using JOIN the data from Table A. In this table there is a column user_id. The user id in table B is the the id from Table A. No i want to get all data from table A but without showing data if the table A id is in the table B column user_id available. I think the trick is the correct usage of JOIN but i need to check the whole column and not just one line.
SQL Query (which is probably not working)
SELECT * FROM tableB
JOIN tableA
ON tableB.user_id = tableA.id
WHERE tableB.user_id != tableA.id
Please see my example i have prepared in Excel:
To select all the data from tableA where id is not available in tableB you don't need join rather you can use not exists or not in.
I would prefer not exists
Using not exists:
SELECT * from tableA a
WHERE NOT EXISTS (
SELECT 1
FROM tableB b
WHERE b.user_id = a.id
);
using not in:
SELECT * from tableA a
WHERE id not in (SELECT user_id FROM tableB );
DB-Fiddle:
create table TableA (id int, name varchar(50), lastname varchar(50));
insert into TableA values(1,'john','smith');
insert into TableA values(2,'Paul','smith');
create table TableB (id int, user_id int, something varchar(50));
insert into TableB values(1,2,'bla');
insert into TableB values(2,3,'bla');
Query: (using not exists)
SELECT * from tableA a
WHERE NOT EXISTS (
SELECT 1
FROM tableB b
WHERE b.user_id = a.id
);
Output:
id
name
lastname
1
john
smith
Query: (using not in)
SELECT * from tableA
WHERE id not in (SELECT user_id FROM tableB );
Output:
id
name
lastname
1
john
smith
db<fiddle here
I think I get what you want. You want not exists:
SELECT *
FROM tableB b JOIN
tableA a
ON b.user_id = a.id
WHERE NOT EXISTS (SELECT 1
FROM tableA a2
WHERE b.user_id = a2.id
);
EDIT:
I wrote the above, but I didn't fully follow the JOIN conditions. You either seem to want to join on id:
SELECT *
FROM tableB b JOIN
tableA a
ON b.id = a.id
WHERE NOT EXISTS (SELECT 1
FROM tableA a2
WHERE b.user_id = a2.id
);
Or no JOIN at all:
SELECT *
FROM tableB b
WHERE NOT EXISTS (SELECT 1
FROM tableA a2
WHERE b.user_id = a2.id
);

Insert into table without duplicates

I have a Table A from where I have to copy Data to Table B. Now problem is In both table A and Table B there is a column ID which is primary key and can't be null.Table A is having Duplicates. Can any one tell me How to insert Data into Table B from Table A without Duplicates?
It would be something like
INSERT INTO TableA(ID) SELECT DISTINCT ID FROM TableB B LEFT JOIN TableA A ON A.ID = B.ID WHERE A.ID IS NULL
You can use the DISTINCT function in a select statement to remove duplicates.
In the example I'm going to assume that both tables have 3 columns called ID, Name and Surname:
insert into tableB (ID, Name, Surname)
select
distinct(ID) as ID
,Name
,Surname
from tableA
;
Please note that the DISTINCT function will provide distinct rows.

Select inner join many-to-one relationship limiting number of results for child table

I have the following tables:
create table TableA (
Id int primary key identity,
Name varchar(80) not null
)
create table TableB (
Id int primary key identity,
TableA_Id int not null foreign key references TableA(Id),
Value varchar(80) not null
)
I would like to write a query similar to
select TableA.Name, TableB.Value
from TableA
inner join TableB on TableA.Id = TableB.TableA_Id
where TableA.Name like 'a%'
order by TableB.Value asc
except that I want only the top 10 within each TableA_Id of TableB.Value (ordered by TableB.Value ascending).
Instead of returning every TableB.Value of each TableA.Name, I want only the top 10 values of each TableA.Name.
What would be such a query?
Use a CROSS APPLY.
A CROSS APPLY allows you to
Use a TOP in the subselect
Use an ORDER BY in the subselect
Match each row of the outer select with every matching row from the subselect
SQL Statement
SELECT TableA.Name
, b.Value
FROM TableA
CROSS APPLY (
SELECT TOP 10 *
FROM TableB
WHERE TableA.Id = TableB.TableA_Id
ORDER BY
TableB.Value
) b
WHERE TableA.Name LIKE 'a%'

SQL: Single select query from 2 Non-Joining tables

I have 2 tables which doesn't have any references to each other and I'm trying to create a third table (for reference lookup) by selecting from fields from both tables.
TableA has an A_ID
TableB has a B_ID
I want to create Table C which has a 1 to 1 reference between A_ID to B_ID
where A_ID = FirstID and B_ID = SecondID, I can't join the 2 tables because there's nothing in common.
Something like:
Insert INTO [TableC]
(FirstID, SecondID)
SELECT
A_ID As FirstID,
(Select B_ID From TableB)
FROM TableA
Basically we are creating a relationship right now with Table C so that we can use it to reference the two tables in the future using the their IDs.
Assuming TableA and TableB truly have nothing in common, then what you want is the Cartesian product, that is, for every row in A times every row in B.
INSERT INTO TableC(FirstID,SecondID)
SELECT A_ID,B_ID
FROM TableA
CROSS JOIN TableB
Perhaps what you really want is to join them by ROW_NUMBER().
INSERT INTO TableC(FirstID,SecondID)
SELECT A_ID,B_ID
FROM (SELECT A_ID,ROW_NUMBER() OVER (ORDER BY whatever) as rownumA FROM TableA) a
FULL OUTER JOIN (SELECT B_ID,ROW_NUMBER() OVER (ORDER BY whatever) as rownumB FROM TableB) b ON a.rownumA=b.rownumB

sql select statement with a group by

I have data in 2 tables, and I want to create a report.
Table A:
tableAID (primary key)
name
Table B:
tableBID (primary key)
grade
tableAID (foreign key, references Table A)
There is much more to both tables, but those are the relevant columns.
The query I want to run, conceptually, is this:
select TableA.name, avg(TableB.grade) where TableB.tableAID = TableA.tableAID
The problem of course is that I'm using an aggregate function (avg), and I can rewrite it like this:
select avg(grade), tableAID from TableB group by tableAID
but then I only get the ID of TableA, whereas I really need that name column which appears in TableA, not just the ID.
Is it possible to write a query to do this in one statement, or would I first need to execute the second query I listed, get the list of id's, then query each record in TableA for the name column... seems to me I'm missing something obvious here, but I'm (quite obviously) not an sql guru...
You can do this:
SELECT avg(b.grade), a.tableAID, a.name
FROM TableA a
JOIN TableB b
ON b.tableAID = a.tableAID
GROUP BY a.tableAID, a.name
Just adding it to the group will work fine in your case.
SELECT AVG(TableB.grade), TableB.tableAID, TableA.Name
FROM TableA INNER JOIN TableB
ON TableA.TableAID = TableB.TableAID
GROUP BY TableA.tableAID, TableA.Name
Alternative answer:
SELECT AVG(b.grade), a.tableAID, MAX(a.name )
FROM TableA a
JOIN TableB b
ON b.tableAID = a.tableAID
GROUP BY a.tableAID
Just to get you thinking.