How should the below be handled in SQL? What would be the where clause?
select *
from tbl_A a
inner join tbl_B b on a.pid = b.pid
where #name# like '%#searchText%
But this column #name# is based on the condition - (if pid is null then use a.pname column else use b.name)
You just use regular AND/OR logic...
select *
from tbl_A a
left join tbl_B b on a.pid = b.pid
where (a.pid is null and a.pname like '%' + #SearchText + '%')
or (a.pid is not null and b.pname like '%' + #SearchText + '%');
You'll be wanting to split the search text out as shown to add the wildcards.
You'll be wanting a left join is pid can be null i.e. there is no match.
Related
I am trying to add two columns together of char data type in order to combine their code with description.
table1 has all of the data I need and I am only referencing table2 in order to get the description.
For example, table1 has column:
Code
1
2
and table 2 has columns:
Code Description
1 Football
2 Soccer
I'm basically trying to write a query where I can have one column show
1 - Football
2 - Soccer
I have tried:
SELECT
a.Code + ' - ' + b.Description
FROM table1 a
LEFT JOIN table2 b
ON a.Code = b.Code
and while this does add the columns together, it also generates a lot of duplicate rows for some reason, I am assuming because of the LEFT JOIN.
Basically I am just wanting that whatever code is in table1, to match that code in table2 and to bring over that Description.
With the Left Join you get the values in Table A that may not exist in Table B. To eliminate the duplicates you could try
SELECT DISTINCT
a.Code + ' - ' + b.Description
FROM table1 a
LEFT JOIN table2 b
ON a.Code = b.Code
OR
SELECT
a.Code + ' - ' + b.Description
FROM table1 a
LEFT JOIN table2 b
ON a.Code = b.Code
GROUP BY a.Code, b.Description
You could use ISNULL to handle missing value from table2:
SELECT
a.Code + ISNULL(' - ' + b.Description, '')
FROM table1 a
LEFT JOIN table2 b
ON a.Code = b.Code
use coalesce in case of null for 2nd table and use distinct incase of avoid duplicate
SELECT distinct a.Code +' - ' + coalesce(b.Description,'')
FROM table1 a
LEFT JOIN table2 b
ON a.Code = b.Code
or try like below and i dont think you needed join you can do it just by using 2nd tabale
SELECT
b.Code ||' - ' || b.Description)
from
table2 b
What is the relationship between table1 and table2? The only way I see the above query returning duplicates is: If relationship between table1 and table2 is 1:Many. Meaning one row in table1 can match to multiple rows in table2.
Do you need to fetch a code that exists in table1 even if it does not have a corresponding description in table2? If so, use a LEFT JOIN like below.
If table2 has direct duplicates, then using a DISTINCT will remove
duplicates in the final result:
SELECT DISTINCT
a.Code + ' - ' + COALESCE(b.Description, '')
FROM table1 a
LEFT JOIN table2 b
ON a.Code = b.Code;
If one code has multiple different descriptions in table2, then your
final resultset is expected to have multiple rows for the same code
but with different description by running the above query because of
the nature of data in the tables.
Do you need to fetch a code that exists in table1 only if it has a corresponding description in table2? If so, use a INNER JOIN like below.
SELECT DISTINCT
a.Code + ' - ' + b.Description
FROM table1 a
INNER JOIN table2 b
ON a.Code = b.Code;
Suppose i have column a in one table and column 2 in another. They are both navchar. Column 2 ends with '-US'. How do I join the two tables, provided that column 1 is the same as 2 but without the us ending?
You could do either
SELECT
a.Field1
,a.Field2
,b.Field3
FROM TableA a
JOIN TableB b
ON a.Fieldname + '-US' = b.FieldName
or if it's not always going to end in -US then you could try this
SELECT
a.Field1
,a.Field2
,b.Field3
FROM TableA a
JOIN TableB b
ON b.FieldName LIKE a.FieldName + '%'
The obvious thing to do is to take the -US suffix into account:
on t2.c2 = t1.c1 + '-US'
or perhaps:
on t1.c1 = left(t2.c2, len(t2.c2) - 3)
If you want performance, you might consider a computed column with an index. Something like this:
alter table t1 add c1_us as (c1 + '-US');
create index t1_c1_us on t1(c1_us);
This would then allow an index to be used for a condition such as:
on t2.c2 = t1.c1_us
I am using MS SQL SERVER 2008R2. i have two tables A and B as
create table A(
id int primary key, name Varchar(20));
create table B(
id int primary key, user_name Varchar(20));
insert into A values(1,'A1');
insert into A values(2,'A2');
insert into A values(3,'A3');
insert into A values(4,'A4');
insert into A values(5,'A5');
Now my problem is :
select A.*
from A left outer join B on A.id = B.id
where B.user_name like '%';
or
select A.*
from A left outer join B on A.id = B.id
where B.user_name like '%%';
Above written query does not return any records even though left table have 5 entries in it. without any filter on right table it works fine.
select A.* from A left outer join B on A.id = B.id
this query will give you out put like this...
id name id user_name
1 A1 NULL NULL
2 A2 NULL NULL
3 A3 NULL NULL
4 A4 NULL NULL
5 A5 NULL NULL
and you are comparing username using like with null
select A.* from A left outer join B on A.id = B.id where B.user_name like '%%';
hence it will not give you any output
you should try following query
select A.*,b.* from A left outer join B on A.id = B.id where (b.user_name like '%%' or b.user_name is null)
In your scenario...first left join is happening it is finding 5 entries and then on that record set sql sever is applying filter of user_name and as user_name for all rows is null..no records are getting displayed.
you can change your query to
select A.* from A left outer join B on A.id = B.id where ISNULL(B.user_name,'') like '%%';
You are using wild card for comparing null values as well,
Use this,
SELECT a.* FROM a LEFT OUTER JOIN b ON a.id = b.id WHERE b.user_name LIKE '%' OR b.user_name IS NULL;
Since all values in table B are NULL, any wildcard match on NULL values will return NULL.
So the condition where B.user_name like '%'; translates into where NULL like '%'; which evaluates to NULL as NULL cannot be compared with any value.
select A.* from A left outer join B on
A.id = B.id where COALESCE(B.user_name,'') like '%%';
select A.* from A left outer join B on
A.id = B.id where COALESCE(B.user_name,'') like '%';
supporting sql fiddle : http://sqlfiddle.com/#!6/1ca91/8
Note that the COALESCE is ANSI, and therefore supported in Oracle, SQL Server and PostGres and does shortcut evaluation. n
Edit: Based on new information that this same query should work in all SQL Server, PostGres and Oracle. I am changing the SQL query to
use COALESCE instead which is supported in all
Unless you use ISNULL() and check like this where
ISNULL(B.user_name,'') like '%';
select A.* from A left outer join B on
A.id = B.id where ISNULL(B.user_name,'') like '%%';
select A.* from A left outer join B on
A.id = B.id where ISNULL(B.user_name,'') like '%';
See this fiddle
http://sqlfiddle.com/#!6/1ca91/6
Please try this one:
select A.* from A
left outer join (SELECT * FROM B where user_name like '%') X on A.id = X.id;
I am new to SQL Server so request you to not get offended by silly question.
I have six disjointed tables (table1, table2 (two columns to be queried), table3, table4, table5, table6 (This is child table of table 5)) in my database.
These are dissimilar tables and I want to use single query to search data from one column in each table and if found then it populate in rows.
I am running following query
SELECT
table1.*
, table2.*
, table3.*
, table4.*
, table5.*
, table6.*
FROM
dbo.table1
FULL OUTER JOIN
dbo.table2 ON table1.col1 = table2.col_A OR table1.col1 = table2.col_B
FULL OUTER JOIN
dbo.table3 ON table2.col_A = table3.col_F OR table2.col_B = table3.col_F
FULL OUTER JOIN
dbo.table4 ON table3.col_F = table4.col_I
FULL OUTER JOIN
dbo.table5 ON table4.col_I = table5.col_N
INNER JOIN
dbo.table6 ON table5.col_N = table6.col_U OR table5.col_N = table6.col_V
WHERE
table1.col1 LIKE '%' + USERINPUT + '%'
OR table2.col_A LIKE '%' + USERINPUT + '%'
OR table2.col_B LIKE '%' + USERINPUT + '%'
OR table3.col_F LIKE '%' + USERINPUT + '%'
OR table4.col_I LIKE '%' + USERINPUT + '%'
OR table5.col_N LIKE '%' + USERINPUT + '%'
However I am not getting results from all the tables. But when I run individually I get correct results. For example
SELECT table1.*
FROM dbo.table1
WHERE
table1.col1 LIKE '%' + USERINPUT + '%'
SELECT table5.* , table6.*
FROM
dbo.table5
INNER JOIN
dbo.table6 ON table5.col_N = table6.col_U OR table5.col_N = table6.col_V
WHERE
table5.col_N LIKE '%' + USERINPUT + '%'
All help appreciated to solve the issue. In short want to have single query that runs across all the table and bring out matching rows ONLY
I think the issue here is that you are using full outer join, but the conditions require matches.
For instance, consider the join to table4:
ON table3.col_F = table4.col_I
Well, to get any matching row from Table4, you have to have a non-NULL value in table3.col_F. But, because of the full outer join, there are likely to be many NULL values. This doesn't quite turn the structure into inner join, but it does end up with many table4 values on their own row, with all the other values being NULL.
Unless you really know what you are doing, you probably do not need full outer joins. Sometimes, you can re-phrase this type of query as a union all with an aggregation or just use left join or inner join instead.
I'm trying to do a simple LEFT JOIN with tables with 2 IDs - basically an ID and Sub-ID. Each row has an ID, but not necessarily a Sub-ID. When a Sub-ID exists, I want to join based on that, if not join on the ID. I'd imagine something like
SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON CASE WHEN SUB_ID IS NOT NULL THEN
a.SUB_ID = b.SUB_ID
ELSE
a.ID = b.ID END
AND
a.otherfield = b.otherfield
But I couldn't get anything like this to work, so instead I had to do 2 queries with a UNION (one that joined on SUB_ID WHERE SUB_ID IS NOT NULL and another that joined on ID WHERE SUB_ID IS NULL.) It worked but I can't imagine there isn't a way to do it. If it helps, my ID and SUB_ID values look like this:
ID SUB_ID
10000 NULL
10001 NULL
10001 10001-3
10001 10001-5
10014 NULL
Any suggestions on how to achieve this without doing a UNION? Thanks in advance!!
We can use COALESCE for this purpose:
SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON COALESCE(a.SUB_ID,a.ID) = COALESCE(b.SUB_ID,b.ID)
COALESCE returns value of first not null parameter from left.
Here is the code at SQL Fiddle
This should work for you.
SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON ((b.SUB_ID IS NOT NULL AND a.SUB_ID = b.SUB_ID) OR
(a.ID = b.ID))
AND a.otherfield = b.otherfield
Interesting.
SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON (
a.SUB_ID = b.SUB_ID
OR (a.SUB_ID IS NULL AND b.SUB_ID IS NULL AND a.ID = b.ID)
)
AND a.otherfield = b.otherfield
That might well work. It's NOT going to be fast, though.
Depending on the state of your data and what you want to achieve, you might want to change the join clause to
ON (
a.SUB_ID = b.SUB_ID
OR (a.SUB_ID IS NULL AND a.ID = b.ID)
OR (b.SUB_ID IS NULL AND a.ID = b.ID)
)
AND a.otherfield = b.otherfield
... instead.
You could JOIN the table twice:
SELECT ...
FROM tablename a
LEFT JOIN tablename b
ON a.SUB_ID = b.SUB_ID
AND a.otherfield = b.otherfield
LEFT JOIN tablename c
ON a.ID = b.ID
AND a.SUB_ID IS NULL
AND a.otherfield = c.otherfield
Then use ISNULL to get the columns, e.g.
ColumnName = ISNULL(b.ColumnName, c.ColumnName)
It depends on your indexes, but I suspect this may get optimised better than having a conditional join clause.
Try something like this:
SELECT *
FROM TABLENAME A
LEFT JOIN TABLENAME B
ON (A.SUB_ID IS NOT NULL AND A.SUB_ID = B.SUB_ID)
OR (A.SUB_ID IS NULL AND A.ID = B.ID)