Selecting other columns if one column is Null - sql-server

If B.[Name] has value it well select the the following
Select
B.[Name],
A.[Address],
A.TIN,
A.AuthorizedRep1Name,
A.AuthorizedRep1Email,
A.AuthorizedRep1Contact,
A.AuthorizedRep2Name,
A.AuthorizedRep2Email,
A.AuthorizedRep2Contact,
A.RefundOfSecDep,
A.PayeeAddress,
A.PayeeTIN
From MembersTbl A
join UserTbl B
on A.UserID = B.ID
And if the B.[Name] is Null It will Select the following
Select
A.[Address],
A.TIN,
A.AuthorizedRep1Name,
A.AuthorizedRep1Email,
A.AuthorizedRep1Contact,
A.RefundOfSecDep,
A.PayeeAddress,
A.PayeeTIN
From MembersTbl A
What will I do?

You can check with creating a variable and assigning their values as shown below.
declare #name varchar(20)
set #name = (select name from YourTable b where ...)
Now to check
if(#name is not null)
begin
----Your first query.
end
else
begin
----Your second query
end

You don't need to do extra effort just add left join in your second query as both query return same data except extra columns.
You can use result according to you requirement based on your condition like B.Name is null or not.
Example :
Select
B.[Name],
A.[Address],
A.TIN,
A.AuthorizedRep1Name,
A.AuthorizedRep1Email,
A.AuthorizedRep1Contact,
A.AuthorizedRep2Name,
A.AuthorizedRep2Email,
A.AuthorizedRep2Contact,
A.RefundOfSecDep,
A.PayeeAddress,
A.PayeeTIN
From MembersTbl A
left join UserTbl B
on A.UserID = B.ID
I hope it will help you :)

Related

Find all lines where a value exists in one line

Here is my query
select order_no, pkg_no, zone_no
from T_DETAIL_ITEM a
where order_no = 495
order by order_no, pkg_no
For a given package I have zone number = 0
What I need to do is return all the lines with the pkg_no = 1597. Because one where exists with a zero zone.
I tried a few different 'where exists' lines and it isn't working.
Try to self join.
This way you can put your requirement in the second table "instance" but retrieve everything from that table matches based on another common field.
select distinct a.order_no, a.pkg_no, a.zone_no
from T_DETAIL_ITEM a
join T_DETAIL_ITEM b on b.pkg_no = a.pkg_no
where b.zone_no = 0
order by a.order_no, a.pkg_no
The accepted answer is good, but I had saw that you noted you tried EXISTS, so I wrote this example up using that method.
SELECT *
FROM T_Detail_Item d
WHERE exists (SELECT * FROM T_Detail_Item dx WHERE dx.pkg_no = d.pkg_no AND dx.zone_no = 0)
One way is to self reference the table in a left join and only include those with a zone_no=0, within the join clause. The filter out non-matching records by excluding records that do not match from the left join, T2.pkg_no = NULL.
SELECT
T1.pkg_no, T1.zone_no
FROM
T_DETAIL_ITEM T1
LEFT OUTER JOIN T_DETAIL_ITEM T2 ON T2.pkg_no = T1.pkg_no AND T2.zone_no = 0
WHERE
NOT T2.pkg_no IS NULL
If I correctly understood the question, you need something like this
BEGIN
declare #str varchar(max);
set #str='';
SELECT #str=#str+ [YOURCOLUMB]
FROM [YOURTABLE]
SELECT #str
END

How to properly join when comparing the difference between two tables pertaining to specific fields

I'm having problems writing this query. So I'm comparing a temp table to a table within our database. I want to find any records that don't have the same Case_Number the same Id_Number combination between the two table. The query I am using only provides me one or the other depending on how I join them. If I join by Case_Number, it returns the Case_Number records that do not match between the two tables. If I join by Id_Number, it will return the Id_Numbers that do not match between the two tables.. Is there a way to join by both Case_Number and ID_Number so that the query returns both? I would also like to know if it would be possible for me to include an "If Exist" to the query? Code below
SELECT T1.Case_Number, T1.Id_Number, T1.FirstDate, T1.LastDate, T2.Case_Number, T2.Id_Number, T2.FirstDate, T2.LastDate
FROM dbo.table T
inner join #TempTable T2
on T1.Id_Number = T2.Id_Number
--on T1.Case_Number = T2.Case_Number
where T1.LastDate is null
and T1.Case_Number <> T2.Case_Number
OR T1.Id_number <> T2.Id_Number
Use or in inner join statement
SELECT T1.Case_Number,
T1.Id_Number,
T1.FirstDate,
T1.LastDate,
T2.Case_Number,
T2.Id_Number,
T2.FirstDate,
T2.LastDate
FROM dbo.table T
INNER JOIN #TempTable T2 ON (T1.Id_Number = T2.Id_Number
OR T1.Case_Number = T2.Case_Number)
WHERE T1.LastDate IS NULL
AND T1.Case_Number <> T2.Case_Number
OR T1.Id_number <> T2.Id_Number
This should find both - firsst colum tells you what is the case
(
SELECT 'in Table not in Temp' as R,
T1.Case_Number as 'T1.Case_Number',
T1.Id_Number as 'T1.Id_Number',
T1.FirstDate as 'T1.FirstDate',
T1.LastDate as 'T1.LastDate',
null as 'T2.Case_Number',
null as 'T2.Id_Number',
null as 'T2.FirstDate',
null as 'T2.LastDate'
FROM dbo.table T1
where not exists (
select 1
from #TempTable T2
where T1.Case_Number == T2.CaseNumber
and T1.Id_Number == T2.Id_Number)
)
UNION ALL
(
SELECT 'in temp, not in list' as R
null as 'T1.Case_Number',
null as 'T1.Id_Number',
null as 'T1.FirstDate',
null as 'T1.LastDate',
T2.Case_Number as 'T2.Case_Number',
T2.Id_Number as 'T2.Id_Number',
T2.FirstDate as 'T2.FirstDate',
T2.LastDate as 'T2.LastDate'
FROM #TempTable T2
where not exists (
select 1
from dbo.table T1
where T1.Case_Number == T2.CaseNumber
and T1.Id_Number == T2.Id_Number )
)
Add the T1.LastDate is null - not sure where you want it.
You probably need to tweak the column names , I switched T1/T2 for 2nd statement so column will be the same table all the time, but names have duplicates.

Aggregate function not allowed in Set statment in TSQL

I need to update one table with values from another table (msdb.dbo.sysjobhistory). Since I need to get the max values of the run_time and run_date, I kept getting 'aggregate function not allowed in set statement' error. As a workaround, I tried the following but something isn't right because ALL the values in every row are the same, indicating either an error in the join or something I can't figure out.This is what I have (which is not correct):
UPDATE inventory.dbo.books SET
auth_time = t1.at,
auth_date = t1.ad
FROM (SELECT MAX(run_time) AS at, MAX(run_date) AS ad
FROM msdb.dbo.sysjobhistory h
INNER JOIN inventory.dbo.books t
ON h.job_id = t.jobid) t1
ALSO, I need to be able to convert the run_time into decimal(10,2) format (as the auth_time field is that) and run_date into datetime (as auth_time is datetime format).
You're so close!
Just move your subquery reference from the From Clause to a subquery in the Set for each field.
Try this:
UPDATE inventory.dbo.books SET
auth_time = (SELECT MAX(run_time)
FROM msdb.dbo.sysjobhistory h
INNER JOIN inventory.dbo.books t
ON h.job_id = t.jobid)
, auth_date = (SELECT MAX(run_date)
FROM msdb.dbo.sysjobhistory h
INNER JOIN inventory.dbo.books t
ON h.job_id = t.jobid);
The subquery in the SET for each field essentially returns a single value when the subquery is executed. Therefore, the use of a subquery doesn't break any of the rules of the set operation.
If your logic starts getting too complicated and your set fields too numerous to want to repeat everything as a subquery for each field, then you can also use a CTE.
With CTE as (
Select MAX(run_time) as at
, MAX(run_date) as ad
FROM msdb.dbo.sysjobhistory h
INNER JOIN inventory.dbo.books t
ON h.job_id = t.jobid
)
Update #Temp
Set auth_time = CTE.at
, auth_date = CTE.ad
From CTE
Let me know if you have any questions!
You can join to a subquery.
And in that subquery you're allowed to use group by.
Then do the casts or converts when the destination fields are set.
For example:
UPDATE b
SET
auth_time = left(replace(cast(h.max_run_time as varchar),':',''),8),
auth_date = cast(h.max_run_date as datetime)
FROM inventory.dbo.books b
JOIN (
select
job_id,
max(run_time) as max_run_time,
max(run_date) as max_run_date
from msdb.dbo.sysjobhistory
group by job_id
) h
ON (b.job_id = h.job_id);
I didn't know what kind of number is expected in that auth_time.
So the max_run_time is just converted from a TIME to a VARCHAR.
The varchar is implicitly converted to the DECIMAL of the destination field.
For example: time '12:15:25.0000000' --> decimal(10,2) 121525.00

Display common values in two tables that are not present in the third table

The three tables in question are:
Table A - relevant columns are TimeTicket and IdAddress
Table B - relevant columns are CommunicationNumber, TimeCreate and IdAddress.
Table C - relevant columns are CommunicationNumber, LastCalled, NextCall
Table C is created by a join of TableA and TableB on IdAddress
INSERT INTO tblC ([CommunicationNumber], [LastCalled] ,[NextCall])
SELECT T2.CommunicationNumber, T2.TimeCreate, T1.TimeTicket
FROM tblA T1
INNER JOIN tblB T2
ON T1.IdAddress = T2.IdAddress AND T2.CommunicationNumber IS NOT NULL
That's one part of the process, and that's fine.
Now, when there is new data in Table A and Table B, I want to update the data entries in Table C. However, I want to ignore the values from Table A and Table B that I have already entered into Table C.
To achieve this, I used NOT EXISTS and wrote a query that looks like this.
INSERT INTO tblC ([CommunicationNumber], [LastCalled] ,[NextCall])
SELECT T2.CommunicationNumber, T2.TimeCreate, T1.TimeTicket
FROM tblA T1
INNER JOIN tblB T2
ON T1.IdAddress = T2.IdAddress AND T2.CommunicationNumber IS NOT NULL
WHERE NOT EXISTS (SELECT T3.CommunicationNumber
FROM [dbo].[tblPhoneLogRep] T3
WHERE T1.TimeTicket <> T3.NextCall AND T2.TimeCreate <> T3.LastCalled AND T2.CommunicationNumber <> T3.CommunicationNumber)
However, this query always returns an empty set.
Could someone please explain to me what is it that I am doing incorrectly?
Try using the EXCEPT set operator:
INSERT INTO tblC ([CommunicationNumber], [LastCalled] ,[NextCall])
SELECT T2.CommunicationNumber, T2.TimeCreate, T1.TimeTicket
FROM tblA T1
INNER JOIN tblB T2
ON T1.IdAddress = T2.IdAddress AND T2.CommunicationNumber IS NOT NULL
EXCEPT
SELECT CommunicationNumber, LastCalled, NextCall FROM tblC
To fix your existing query, you would need to change your <> operators to = operators, like so:
INSERT INTO tblC ([CommunicationNumber], [LastCalled] ,[NextCall])
SELECT T2.CommunicationNumber, T2.TimeCreate, T1.TimeTicket
FROM tblA T1
INNER JOIN tblB T2
ON T1.IdAddress = T2.IdAddress AND T2.CommunicationNumber IS NOT NULL
WHERE NOT EXISTS (SELECT 1
FROM tblC
WHERE T1.TimeTicket = tblC.NextCall AND T2.TimeCreate = tblC.LastCalled AND T2.CommunicationNumber = tblC.CommunicationNumber)
Personally, I think the EXCEPT syntax is more clear though.
Your issue is that you are essentially using a double negative. You are saying NOT EXISTS and you are setting your WHERE criteria to <>. I think it would work out if you either used EXISTS or change you criteria =.

Conditional JOIN Statement SQL Server

Is it possible to do the following:
IF [a] = 1234 THEN JOIN ON TableA
ELSE JOIN ON TableB
If so, what is the correct syntax?
I think what you are asking for will work by joining the Initial table to both Option_A and Option_B using LEFT JOIN, which will produce something like this:
Initial LEFT JOIN Option_A LEFT JOIN NULL
OR
Initial LEFT JOIN NULL LEFT JOIN Option_B
Example code:
SELECT i.*, COALESCE(a.id, b.id) as Option_Id, COALESCE(a.name, b.name) as Option_Name
FROM Initial_Table i
LEFT JOIN Option_A_Table a ON a.initial_id = i.id AND i.special_value = 1234
LEFT JOIN Option_B_Table b ON b.initial_id = i.id AND i.special_value <> 1234
Once you have done this, you 'ignore' the set of NULLS. The additional trick here is in the SELECT line, where you need to decide what to do with the NULL fields. If the Option_A and Option_B tables are similar, then you can use the COALESCE function to return the first NON NULL value (as per the example).
The other option is that you will simply have to list the Option_A fields and the Option_B fields, and let whatever is using the ResultSet to handle determining which fields to use.
This is just to add the point that query can be constructed dynamically based on conditions.
An example is given below.
DECLARE #a INT = 1235
DECLARE #sql VARCHAR(MAX) = 'SELECT * FROM [sourceTable] S JOIN ' + IIF(#a = 1234,'[TableA] A ON A.col = S.col','[TableB] B ON B.col = S.col')
EXEC(#sql)
--Query will be
/*
SELECT * FROM [sourceTable] S JOIN [TableB] B ON B.col = S.col
*/
You can solve this with union
select a, b
from tablea
join tableb on tablea.a = tableb.a
where b = 1234
union
select a, b
from tablea
join tablec on tablec.a = tableb.a
where b <> 1234
I disagree with the solution suggesting 2 left joins. I think a table-valued function is more appropriate so you don't have all the coalescing and additional joins for each condition you would have.
CREATE FUNCTION f_GetData (
#Logic VARCHAR(50)
) RETURNS #Results TABLE (
Content VARCHAR(100)
) AS
BEGIN
IF #Logic = '1234'
INSERT #Results
SELECT Content
FROM Table_1
ELSE
INSERT #Results
SELECT Content
FROM Table_2
RETURN
END
GO
SELECT *
FROM InputTable
CROSS APPLY f_GetData(InputTable.Logic) T
I think it will be better to think about your query in a different way and treat them more like sets.
I do believe if you make two separate queries then join them using UNION, It will be much better in performance and more readable.

Resources