inner join on multiple conditions when using a database link - sql

Could someone help me figure out why my inner join won't work when I try to use multiple conditions? I'm using a database link to connect my tables, and then using "and" for my second condition. When I only have the first inner join on a.E_id = b.eid it shows results but when I add the second condition it turns up blank...
my code:
select count(*)
from table1#dblink a
inner join table2 b
on a.E_id = b.eid
and a.BUS_ID = b.B_NUMBER
where b.pricing_system = 'M'
;

I have used wildcard character % with like operator. Try below query:
select count(*)
from table1#dblink a
inner join table2 b
on a.E_id = b.eid
and a.BUS_ID like '%'||b.B_NUMBER||'%'
where b.pricing_system = 'M';

If the inner join can't find records with the condition the result will be no rows.
If you want the rows even if the second condition doesn't match, then change it for Left join and change the condition for a Like
And if the 'M' character is in diferents positions of the field, then use the character '%'
You should use this:
select count(*)
from table1#dblink a
Left join table2 b
on a.E_id = b.eid
and a.BUS_ID = b.B_NUMBER
and b.pricing_system = '%M%';

Related

Use Like operator in Select query with results from another Select query

I have a query with inner joins that returns 4-5 rows - the query:
select Table1.valstring Prefix
from TestDB.dbo.SomeCompany PC
INNER JOIN TestDB.dbo.CMCompany CMC ON PC.companyuid = CMC.companyuid
LEFT OUTER JOIN TestDB.dbo.ATRIBUTE Table1 ON Table1.Contract = CMC.contract AND Table1.attribute = 'SomeThing'
LEFT OUTER JOIN TestDB.dbo.ATRIBUTE TheRealPrefix ON TheRealPrefix.Contract = CMC.contract AND TheRealPrefix.attribute = 'SomeOtherPrefix'
where secretCode = 'Mistery'
I would like to feed this query into the another select query that uses like operator with the results from the already described query.
So something like this:
select from taskTable where task like ('%' + select Table1.valstring Prefix
from TestDB.dbo.SomeCompany PC
INNER JOIN TestDB.dbo.CMCompany CMC ON PC.companyuid = CMC.companyuid
LEFT OUTER JOIN TestDB.dbo.ATRIBUTE Table1 ON Table1.Contract = CMC.contract AND Table1.attribute = 'SomeThing'
LEFT OUTER JOIN TestDB.dbo.ATRIBUTE TheRealPrefix ON TheRealPrefix.Contract = CMC.contract AND TheRealPrefix.attribute = 'SomeOtherPrefix'
where secretCode = 'Mistery'
)
If you require a match, then you don't require left joins. So remove them. It is unclear where secretCode comes from; that should be explicit.
The last join on attribute is useless -- not used for filtering. And secretCode does not come from that table (you would get an error because the reference is not qualified).
So, I think this does what you want:
SELECT tt.*
FROM TestDB.dbo.SomeCompany PC JOIN
TestDB.dbo.CMCompany CMC
ON PC.companyuid = CMC.companyuid JOIN
TestDB.dbo.ATRIBUTE a
ON a.Contract = CMC.contract AND a.attribute = 'SomeThing' JOIN
taskTable tt
ON task like CONCAT('%', a.valstring)
WHERE secretCode = 'Mistery'
Try to use this query:
select *
from TestDB.dbo.SomeCompany PC
INNER JOIN TestDB.dbo.CMCompany CMC ON PC.companyuid = CMC.companyuid
LEFT JOIN TestDB.dbo.ATRIBUTE Table1 ON Table1.Contract = CMC.contract AND Table1.attribute = 'SomeThing'
LEFT JOIN TestDB.dbo.ATRIBUTE TheRealPrefix ON TheRealPrefix.Contract = CMC.contract AND TheRealPrefix.attribute = 'SomeOtherPrefix'
LEFT JOIN taskTable ON taskTable.task LIKE '%' + Table1.valstring
where secretCode = 'Mistery'
But keep in mind, if you have many rows in your DB, search by '%' + Table1.valstring is bad practice.

Using a when statement and a custom code inside it

I have this code where i want to implement a complex piece in when statement so i can fix the issue, there are several when statements after the one which i am showing
when d.ID in (1,2,3) and d.today <= '10/11/2018' AND (
select count(1)
from table1 sc
inner join table2 c on c.ID = sc.ID
inner join table3 tc on tc.ID = sc.ID
where sc.sid = 4
and sc.fid is not null
and c.fid = d.facultyid
group by sc.sNum,sc.Fid,sc.todaydate,c.ID,tc.cnum
) B > 5 then 500 else 520 end
An expression of non-boolean type specified in a context where a condition is expected, near 'B'.
You have a spurious table alias B. Remove it
(select count(1)
from table1 sc
inner join table2 c on c.ID = sc.ID
inner join table3 tc on tc.ID = sc.ID
where sc.sid = 4
and sc.fid is not null
and c.fid = d.facultyid
group by sc.sNum,sc.Fid,sc.todaydate,c.ID,tc.cnum
) > 5
I should note that you are likely to now get an error that the subquery returns more than one row. If so, ask another question. This question has been answered.
Include sample data, desired results, an explanation of what the query should do, and a (perhaps simplified) version of your existing query.

select left join table use and condition

these two query output different result,
I have question AND m.status = $1 ...each condition follow the left join table or move to the final part, thats different ??
query 1
SELECT count(mua.*)
AS total_row_count
FROM media_user_action mua
LEFT JOIN media m ON m.id = mua.media_id
AND m.status = $1
LEFT JOIN gallery_media gm ON gm.id = mua.media_id
LEFT JOIN gallery g ON g.id = gm.gallery_id
AND g.status = $1
LEFT JOIN "user" mcbu ON mcbu.id = m.create_by_user_id
AND mcbu.status = $1
LEFT JOIN "user" gcbu ON gcbu.id = g.create_by_user_id
AND gcbu.status = $1
WHERE mua.user_id = $2
query 2
SELECT count(mua.*)
AS total_row_count
FROM media_user_action mua
LEFT JOIN media m ON m.id = mua.media_id
LEFT JOIN gallery_media gm ON gm.id = mua.media_id
LEFT JOIN gallery g ON g.id = gm.gallery_id
LEFT JOIN "user" mcbu ON mcbu.id = m.create_by_user_id
LEFT JOIN "user" gcbu ON gcbu.id = g.create_by_user_id
WHERE
m.status = $1
AND g.status = $1
AND mcbu.status = $1
AND gcbu.status = $1
AND mua.user_id = $2
UPDATE
base on below answer
if I want make sure return result, must all related/left join table status both equal $1, ( join table recode could be null) so I have to add AND x.status .. follow the join table, right?
When you use left outer join, value of the right table may be NULL.
For simplicity's sake, let say we have
Table A (id, name) and Table B (fid, status)
Then query1 will be like
select A.id, B.status
from A
left join (select * from B where status = $1)
on A.id = B.fid;
so result could have B.status is NULL
And query2 will be like
select C.*
from (select A.id, B.status
from A
left join B
on A.id = B.fid
) C
where C.status = $1;
It's equal to
select *
from A
inner join B
on A.id = B.fid
where B.status = $1;
So B.status must exactly be $1, and is never NULL
When you put WHERE conditions on tables that you have LEFT JOIN-ed, and that require some their fields to have non-NULL values, then you are actually converting the LEFT JOIN into an INNER JOIN.
This is because a LEFT JOIN may produce results where the joined table has no matching record. In that case all fields of that "virtual" record have value NULL. So by requiring that one of those fields is not null, you remove those instances from the result.
If on the contrary, you put such conditions in the LEFT JOIN condition, then you do not break this mechanism, where the a non-match will still give a result, albeit with NULL.
An outer join means that additionally to an inner join, when no match is found a mock record with all columns null gets joined.
So let's say for one mua we don't find a matching m. Then we get an m record with all columns null. m.status is null. With WHERE m.status = $1 you dismiss that record, however, so you are where you were with a simple inner join.
Criteria on outer-joined tables belongs in the ON clause.

Inner join on a left join makes the left join behave as a inner join

I have a two lookup tables that I want to inner join on each other, however I only want to left join on my data table.
select * from CLIENT
LEFT JOIN [ENTRY]
on [ENTRY].ENTRY_CODE = CLIENT.CLIENT_COUNTY
and [ENTRY].ENTRY_RECD = 'A'
INNER JOIN [ENTRY_TYPES]
on [ENTRY_TYPES].ENTRY_TYPES_FileRecordID = [ENTRY].ENTRY_TYPE
and [ENTRY_TYPES].ENTRY_TYPES_CODE = 'COUNTY'
and [ENTRY_TYPES].ENTRY_TYPES_RECD = 'A'
where CLIENT_RECD = 'A'
So if ENTRY_TYPES_FileRecordID = ENTRY_TYPE fails I do not want that ENTRY record to be available as a left join item for the join on to CLIENT.
The way the above code is written the left join on ENTRY is behaving like a inner join.
Figured it out on my own as I was typing up the question, I needed to separate out the inner join as a sub-query
select * from CLIENT
left join
(
select ENTRY_CODE, ENTRY_NAME
from [ENTRY]
inner join [ENTRY_TYPES] on ENTRY_TYPES_FileRecordID = ENTRY_TABLE
and ENTRY_TYPES_CODE = 'COUNTY'
and ENTRY_TYPES_RECD = 'A'
where ENTRY_RECD = 'A'
) as CountyLookup on CLIENT_COUNTY = ENTRY_CODE
where CLIENT_RECD = 'A'
You already found a solution yourself, but now you made it a subquery. You can also do this by moving some parts around in your original query and adding two brackets.
So this is just to show an alternative:
SELECT *
FROM [CLIENT]
LEFT JOIN ([ENTRY] --opening bracket
INNER JOIN [ENTRY_TYPES]
ON [ENTRY_TYPES].[ENTRY_TYPES_FileRecordID] = [ENTRY].[ENTRY_TYPE]
AND [ENTRY_TYPES].[ENTRY_TYPES_CODE] = 'COUNTY'
AND [ENTRY_TYPES].[ENTRY_TYPES_RECD] = 'A') -- closing bracket
ON [ENTRY].[ENTRY_CODE] = [CLIENT].[CLIENT_COUNTY]
AND [ENTRY].[ENTRY_RECD] = 'A'
WHERE [CLIENT_RECD] = 'A'

Conditional Inner Join

I want to be able to inner join two tables based on the result of an expression.
What I've been trying so far:
INNER JOIN CASE WHEN RegT.Type = 1 THEN TimeRegistration ELSE DrivingRegistration AS RReg
ON
RReg.RegistreringsId = R.Id
RegT is a join I made just before this join:
INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id
This SQL-script does not work.
So all in all, if the Type is 1, then it should join on the table TimeRegistration else it should join on DrivingRegistration.
Solution:
In my select statement I performed the following joins:
INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id
LEFT OUTER JOIN TimeRegistration AS TReg ON TReg.RegistreringsId = R.Id AND RegT.Type = 1
LEFT OUTER JOIN DrivingRegistration AS DReg ON DReg.RegistreringsId = R.Id AND RegT.Type <>1
Then I edited my where-clause to output the correct, depending on the RegType, like this:
WHERE (CASE RegT.Type WHEN 1 THEN TReg.RegistreringsId ELSE DReg.RegistreringsId END = R.Id)
Try putting both tables in the query using LEFT JOIN's
LEFT JOIN TimeRegistration TR ON r.rid = TR.Id AND RegT.type =1
LEFT JOIN DrivingRegistration DR ON r.rid = DR.Id AND RegT.type <>1
Now, in you select clause, use
CASE RegType.Type WHEN 1 THEN TR.SomeField ELSE DR.someField END as SomeField
The other option is to use dynamic SQL
You probably need to perform two left joins, one onto TimeRegistration and one onto DrivingRegistration, and return the fields you want from the appropriate join table something like this:
LEFT JOIN TimeRegistration ON TimeRegistration.RegistreringsId = R.Id
LEFT JOIN DrivingRegistration ON DrivingRegistration.RegistreringsId = R.Id
and you select statement would be something like this:
SELECT CASE WHEN RegT.Type = 1 THEN TimeRegistration.Foo ELSE DrivingRegistration.Bar END
I like what you're trying to do, but I don't think SQL is that clever.
SELECT
R.foo, tr.bar
FROM
SomeTable AS R
INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id
AND RegT1.Type = 1
INNER JOIN TimeRegistration AS tr ON /* whatever */
UNION
SELECT
R.foo, dr.bar
FROM
SomeTable AS R
INNER JOIN RegistrationTypes AS RegT ON R.RegistrationTypeId = RegT.Id
AND RegT1.Type = 2
INNER JOIN DrivingRegistration AS dr ON /* whatever */
So I had a scenario where there were three email columns in one table (don't ask why) and any of them could be null (or empty). In this example code I will just deal with a case where it is null.
I had to join it to another table by any of the emails to retrieve the users firstname.
Here is what worked
select
m.email1,
m.email2,
m.email3,
m2.firstName
from MyTable m
left join MyOtherTable m2 on m2.Email =
case when m.email1 is null then
case when m.email2 is null then
case when m.email3 null then
'nonexistent#mydomain.com' -- i stopped here
else m.email3 end
else wm.email2 end
else m.email1 end
Obviously you would include further conditions like
case when m.email1 is null or m.email1 = '' then ...
To cover for empty values.