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.
Related
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.
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;
I am trying to join two tables in SQL Server. Their are no PK / FK in the tables so I have to join on a few conditions.
What I want to have happen is if I am unable to match on my first criteria I then want to join on different criteria. I was thinking there could be way to do this using a case statement... If it matches on my first condition then all is good, if it does not match on the first condition then try to join on a different condition.
Here is what I have so far.
SELECT *
FROM Table1
INNER JOIN Table2
ON Table1.DOS = CAST(SUBSTRING(Table2.SurgeryDate, 6, 2) + '/' + SUBSTRING(Table2.SurgeryDate, 9, 2) + '/' + SUBSTRING(Table2.SurgeryDate, 1, 4) AS DATE)
AND Table1.DateOfBirth = CAST(SUBSTRING(Table2.BirthDate, 6, 2) + '/' + SUBSTRING(Table2.BirthDate, 9, 2) + '/' + SUBSTRING(Table2.BirthDate, 1, 4) AS DATE)
AND Table1.Gender = CASE WHEN Table2.gender = 'Male' THEN 'M'
WHEN Table2.gender = 'Female' THEN 'F'
ELSE 'U'
END
AND LTRIM(RTRIM(Table1.HspId)) = LTRIM(RTRIM(Table2.HspId))
---If those people who do not match on the above criteria then I would want to match them on their last name.
Sample data will be needed to give a specific answer, but here are a couple general approaches:
You can use OR while ruling out the previous condition:
SELECT cols
FROM Table1 t1
JOIN Table2 t2 ON t1.col1 = t2.col1
OR (t1.col1 <> t2.col1 AND t1.col2 = t2.col2)
Note you have to rule out the previous condition to create the join predicate hierarchy and avoid duplicates.
Another way is to use repeated LEFT JOINs for each condition and add NULL handling:
SELECT COALESCE(t2.col1, t3.col1)
FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.col1 = t2.col1
LEFT JOIN Table2 t3 ON t1.col2 = t3.col2
WHERE COALESCE(t2.col1, t3.col1) IS NOT NULL
COALESCE() returns the first non NULL value. The LEFT JOINs will return NULL if the join does not find a match row. Thus, the select COALESCE() is handling 'displaying' the correct column based on the join hierarchy order. The where COALESCE() is filtering out the rows where none of joins are successful (recreating the INNER JOIN you have in your current query)
The second approach, while ugly, can perform better because OR queries have trouble optimizing properly.
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 aware of using where and like this
select * from Table1
join table2
on table1.column like %text%
i want to extend the same logic to the column. i.e
select * from Table1
join table2
on table1.column like %table2.column%
This is impossible on SQL? is there an alternative for this?
Thanks
Try to get into the habit of always specifying the DB engine you are using and including sample data and expected output based on that sample data. In this case the sample data etc can help us provide a more relevant answer. there may be a better solution to your problem than using like in your join clause.
but for the simple example you have given the below should work.
select * from Table1
join table2
on table1.column like '%' + table2.column + '%'
EDIT
From this resource it seems proc-sql uses double pipe || for string contatenation and double quotes for strings so try the new version below.
select * from Table1
join table2
on table1.column like "%" || table2.column || "%"
Try this
select * from Table1
join table2
on table1.column like '%' + table2.column + '%' COLLATE Latin1_General_CS_AS
where (COLLATE Latin1_General_CS_AS) stands for case sensitive in Microsoft SQL Server