Using a when statement and a custom code inside it - sql

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.

Related

inner join on multiple conditions when using a database link

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%';

SQL where clause in nested query with column that doesnt exist in nested query

I wrote the following query and it works:
select * from processed p
inner join data d on d.dataId = p.dataid
where assetid in (select a.assetid from dbo.file f
inner join asset a on a.assetName = f.fileNumber
inner join configMapping c on c.assetId = a.assetid
WHERE p.id in (2,11) and rawConfig = 1)
However, I realised this shouldn't work. The query should be written as:
select * from processed p
inner join data d on d.dataId = p.dataid
where assetid in (select a.assetid from dbo.file f
inner join asset a on a.assetName = f.fileNumber
inner join configMapping c on c.assetId = a.assetid
WHERE rawConfig = 1)
and p.id in (2,11)
The nested query is only looking for assetid's. Furthermore, running the nested query on its own wouldn't work because id isn't in those three tables:
select a.assetid from dbo.file f
inner join asset a on a.assetName = f.fileNumber
inner join configMapping c on c.assetId = a.assetid
WHERE p.id in (2,11) and rawConfig = 1
Msg 207, Level 16, State 1, Line 44
Invalid column name 'id'.
Apologies for not having testable data to provide, but essentially the question is how does the first query's nested query use a where on a column from its parent query. Logically I would think the nested query would fail and thus the whole query should fail.
I'm using the newest version of SSMS
You have to add condition in the select using case I have shifted the ContractDate but if it doesn't work then you have to shift other conditions too
Select
SUM(case when c.ContractDate >= #ContractDate then c.Price else 0 end) As 'TotalPrice',
SUM(case when c.ContractDate >= #ContractDate then 1 else 0 end) As 'ContractCount'
from Rsv_Contract as c
where c.RegisterUsersId = #RegisterUsersId
and c.contractstate in (1,2)
and c.ContractNumber!='0000000'
and c.ContractNumber!='-1'
Group by CAST(c.ContractDate AS DATE)
You can use EXISTS clause of sql.
select *
from processed p
join data d
on d.dataid = p.dataid
where p.id in (2, 11)
and exists (select 1
from dbo.file f
join asset a
on a.assetname = f.filenumber
join configmapping c
on c.assetid = a.assetid
where a.assetid = p.asset_id
and rawconfig = 1)
Sorry guys, my bad not mentioning the code beforehand.
Hope this will solve your problem.
I found the answer here:
https://learn.microsoft.com/en-us/sql/relational-databases/performance/subqueries?view=sql-server-2017
Important
If a column is referenced in a subquery that does not exist in the table referenced by the subquery's FROM clause, but exists in a table referenced by the outer query's FROM clause, the query executes without error. SQL Server implicitly qualifies the column in the subquery with the table name in the outer query.
It will effectively refactor the query into a series of joins before executing.

SQL Multiple Joins not working as expected

I have following query not working when I try to join all 4 tables (It is taking over an hour to run, I have to eventually kill the query without any data being returned).
It works when Table 1,2 & 3 are joined AND Then If I try Table 1,2 & 4 join but not when I attempt to join all 4 tables below.
Select * From
(Select
R.ID, R.MId, R.RId, R.F_Name, R.F_Value, FE.FullEval, M.Name, RC.CC
FROM Table1 as R
Inner Join Table2 FE
ON R.ID = FE.RClId and R.MId = FE.MId and R.RId = FE.RId
Inner Join Table3 as M
ON R.MId = M.MId and FE.MId = M.MId
Inner Join Table4 as RC
ON R.RId = RC.RId and FE.RId = RC.RId and FE.Date = RC.Date
) AS a
NOTE:
1) RId is not available in table3.
2) MId is not available in table4.
Thanks for help.
Since you mentioned that you don't have permission to view the query plan, try breaking down into each table join. You can also check which table join is taking time to retrieve records. From there, you can investigate the data why it's taking time. It may be because of non-availability of column keys in Table 3 and Table 4?
WITH Tab1_2 AS
(SELECT r.ID, r.MId, r.RId, r.F_Name, r.F_Value, fe.FullEval, fe.date
FROM Table1 as r
INNER JOIN Table2 fe
ON r.ID = fe.RClId
AND r.MId = fe.MId
AND r.RId = fe.RId
WHERE ... -- place your conditions if any
),
Tab12_3 AS
(SELECT t12.*, m.Name
FROM Tab1_2 t12
INNER JOIN Table3 as m
ON t12.MId = m.MId
WHERE ... -- place your conditions if any
),
Tab123_4 AS
(SELECT t123.ID, t123.MId, t123.RId, t123.F_Name, t123.F_Value, t123.FullEval, rc.CC
FROM Tab12_3 t123
INNER JOIN Table4 as rc
ON t123.RId = rc.RId
AND t123.Date = rc.Date
WHERE ... -- place your conditions if any
)
SELECT *
FROM Tab123_4 t1234

Get DISTINCT record using INNER JOIN

I have the follwong Query on multi tables
SELECT DISTINCT b.BoxBarcode as [Box Barcode], (select case when b.ImagesCount IS NULL
then 0
else b.ImagesCount end) as [Total Images], s.StageName as [Current Stage] ,d.DocuementTypeName as [Document Type],
u.UserName as [Start User],uu.UserName as [Finished User]
FROM [dbo].[Operations] o
inner join dbo.LKUP_Stages s on
o.stageid=s.id
inner join dbo.LKUP_Users u on
u.id=o.startuserid
left join dbo.LKUP_Users uu on
uu.id=o.FinishedUserID
inner join boxes b on
b.id=o.boxid
inner join LKUP_DocumentTypes d on
d.ID = b.DocTypeID
where b.IsExportFinished = 0
when i select count from the Boxes table where IsExportFinished = 0
i got the Count 42 records, when i run the above qoury i got 71 records,
i want just the 42 records in Boxes table to retrived.
You are doing a one-to-many join, i.e. at least one of the tables have multiple rows that match the join criteria.
Step one is to find which table(s) that give the "duplicates".
Once you have done that you may be able to fix the problem by adding additional criteria to the join. I'm taking a guess that the same boxid occurs several times in the Operations table. If that is the case you need to decide which Operation row you want to select and then update the SQL accordingly.
Try this one -
SELECT
Box_Barcode = b.BoxBarcode
, Total_Images = ISNULL(b.ImagesCount, 0)
, Current_Stage = s.StageName
, Document_Type = d.DocuementTypeName
, Start_User = u.UserName
, Finished_User = uu.UserName
FROM (
SELECT DISTINCT
o.stageid
, o.boxid
, o.startuserid
, o.FinishedUserID
FROM dbo.[Operations]
) o
JOIN dbo.LKUP_Stages s ON o.stageid = s.id
JOIN dbo.boxes b ON b.id = o.boxid
JOIN dbo.LKUP_DocumentTypes d ON d.id = b.DocTypeID
JOIN dbo.LKUP_Users u ON u.id = o.startuserid
LEFT JOIN dbo.LKUP_Users uu ON uu.id = o.FinishedUserID
WHERE b.IsExportFinished = 0
I guess that if you change your LEFT JOIN into INNER JOIN you will get 42 records as requested.

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.