SQL case where in with two conditions - sql

Table_A Table_B
CityID StreetID AreaID PersonName CityID StreetID
Select tabB.PersonName from Table_B tabB WHERE CityID IN (SELECT tabB.StreetID
FROM Table_B tabB Where AreaID = 5) AND StreetID
I created a subquery to select all StreetID id in table b where areaID = 5. there are duplicate street id and unique City id. My problem is city id and street id of table B should match table A. How should I put this in query?

Inner join the tables then select PersonName and the StreetID...

You are looking for all persons where the area 5 is among the areas the person's street belongs to. (At least this is what your query suggests.)
It's a pity that SQL Server is not able to deal with WHERE (CityID, StreetID) IN like some other DBMS do.
So use EXISTS instead:
select personname
from table_b b
where exists
(
select null
from table_b2
where b2.areaid = 5
and b2.cityid = b.cityid
and b2.streetid = b.streetid
);

SELECT tabB.PersonName
FROM Table_B tabB
INNER JOIN Table_A tabA
ON
tabB.CityID = tabA.CityID AND tabB.StreetID = tabA.StreetID AND tabA.AreaID = 5

Related

Returning the first result from another table if statement is true

So I'm struggling to find the logic for the next problem:
I got 2 tables
TABLE A has the following column
Postalcode
1111
2222
3333
4444
TABLE B has the following column
Postalcode
1111AA
1111BB
1111CA
2222AA etc
What I would like to have is that if the Postalcodes first 4 numbers are found from Table A in table B, then I would like to have the first result of that postalcode from Table B (4digits+2letters).
e.g. if the postalcode in A is 1111 and substring(postalcode, 1, 4) of Table B is also 1111, then return the first result of that postalcode from Table B --> 1111AA
I can't seem to find the answer for this and I'm struggling for a while now.
Hope you guys have the solution for me.
If for each record in table A you want to match at most one record from Table B, an OUTER APPLY (SELECT TOP 1 ...) should do the trick.
Try:
select a.PostalCode, b1.Postalcode
from table_a a
outer apply (
select top 1 *
from table_b b
where b.Postalcode LIKE a.Postalcode + '%'
order by b.id
) b1
order by a.PostalCode;
If you wish to omit results that have no matching table_b record, change the OUTER APPLY to a CROSS APPLY. A OUTER APPLY is like a LEFT JOIN while a CROSS APPLY is like an INNER JOIN.
See this db<>fiddle fr a demo.
(Credit Bernd Buffen for the data setup. Note that I changed PostalCode from INT to VARCHAR to simplify the match criteria.)
i have change the sample from #Ergest Basha with a virtual column and index
CREATE TABLE table_a (
Postalcode INT ,
KEY idx_sPortalcode (Postalcode)
);
INSERT INTO table_a VALUES
(1111),
(2222),
(3333),
(4444);
CREATE TABLE table_b (
id INT,
Postalcode VARCHAR(25),
sPostalcode INT AS ( 0 + Postalcode) STORED,
KEY idx_sPortalcode (sPostalcode)
);
INSERT INTO table_b (id,Postalcode) VALUES
(1,'1111AA'),
(2,'1111BB'),
(3,'1111CA'),
(4,'2222AA');
SELECT * FROM table_b;
-- EXPLAIN
SELECT b.Postalcode
FROM table_a a
INNER JOIN table_b b ON b.sPostalcode=a.Postalcode
WHERE a.Postalcode=1111
ORDER BY b.id ASC LIMIT 1;
Something like this: MySQL
select b.Postalcode
from table_a a
inner join table_b b on LEFT(b.Postalcode,4)=a.Postalcode
where a.Postalcode=1111
order by b.id asc limit 1;
Check the demo
SQL Server
select top(1) b.Postalcode
from table_a a
inner join table_b b on LEFT(b.Postalcode,4)=a.Postalcode
where a.Postalcode=1111
order by b.id ;
Demo
Edit based on comments*
I think you need something like below, but check #Bernd Buffen suggestion for performance:
WITH cte AS (
SELECT Postalcode, ROW_NUMBER() OVER ( PARTITION BY LEFT(Postalcode,4) ORDER BY id asc ) row_num
FROM table_b
)
SELECT cte.Postalcode
FROM table_a a
INNER JOIN cte on LEFT(cte.Postalcode,4)=a.Postalcode
WHERE row_num = 1 ;
Demo

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 with two selects and compare

It looks stupid in this example but here is what I want to do:
Table_a:
id fk_b_id full_name
1 [I want '10' here] [I want 'John, Doe' here]
Table_b:
id first_name
10 John
Table_c:
id full_name date
20 John, Doe 2020-01-01
I get all the full names that is not already in c and meets the criteria like this:
select distinct full_name
from Table_c
where full_name not in (
select full_name
from Table_a ) and date > GETDATE()
The result from the query should be inserted into Table_a together with Table_b's id (fk_b_id). So I need a compare between part of Table_a's full_name and Table_b's first_name to get the correct fk. I can do the compare like this:
where Table_b.first_name = LTRIM(RTRIM(RIGHT(Table_c.full_name, CHARINDEX(',', REVERSE(Table_c.full_name))-1 )))
Can I insert all the full names from table c (that meets the criteria) and the fk from table b (where their first names match) into table a in one query?
Sure, just use your condition to JOIN between tables B and C
INSERT INTO Table_a (fk_b_id, full_name)
SELECT DISTINCT b.id, c.full_name
FROM Table_c c
INNER JOIN Table_b b ON b.first_name = LTRIM(RTRIM(RIGHT(c.full_name, CHARINDEX(',', REVERSE(c.full_name))-1 )))
WHERE c.full_name not in (
select a.full_name
from Table_a a ) and c.date > GETDATE()
EDIT:
Also note, that if your table_a.full_name column can have NULL values, NOT IN sub-query will fail to give you expected results. I suggest rewriting it to use NOT EXISTS
WHERE NOT EXISTS
(SELECT * FROM Table_a WHERE Table_a.Full_Name = Table_c.FUll_Name )

Select between multiple lines

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.

Getting the Emp_ID

In Table_A I have atrribute "Verantwortlicher". This attribute contains the last name and the first name of the person respectively i.e. "Doe John"
In Table_B I have two attributes "Lastname_NAM" and "Firstname_NAM" which of course contain lastnames and firstnames of a person respectively i.e.
"Lastname_NAM" - Doe
"Firstname_NAM" - John
Table_A has a foreign key (Responsible_Emp_ID) which is referencing Table_B´s primary key (Emp_ID)
What I would like is to join these two tables so that beside the strig-type full name in the Table_A I also have a ID of that person (which of course comes from Table_B)
I forgot to mention that I need this data so I can FILL the values in aforeign key. Table_A is EMPTY.
I´m using T-SQL
Please help,
Thanks, D.
Try following code
SELECT
B.EmpID,
ISNULL(A.Verantwortlicher,B.Firstname_NAM++B.Lastname_NAM)
FROM
TableB B
LEFT JOIN TableA A
ON B.EmpID = A.Responsible_Emp_ID
Try this:
--Populate TableA
INSERT INTO TableA(Responsible_Emp_ID, Verantwortlicher)
SELECT EmpID, FirstName + ' ' + LastName
FROM TableB B
--SELECT to join the 2 tables
SELECT B.EmpID, A.Verantwortlicher
FROM TableB B
INNER JOIN TableA A
ON B.EmpID = A.Responsible_Emp_ID
--Just make the join
SELECT C.FullName, A.EmpID FROM
(SELECT FirstName + ' ' + LastName AS FullName
FROM TABLE B) C
INNER JOIN TableA A
ON C.FullName = A.Verantwortlicher