How to add a extra column at runtime in SQL Server - sql-server

My query is
SELECT
RemainingQty, CompletedQty
FROM
tblJobStatus AS JT
LEFT OUTER JOIN
TBLJOBWORKS AS TJ ON JobWorksId = TaskId
LEFT OUTER JOIN
tblTotalJob AS T ON T.Id = JobID
WHERE
JT.ProductID = '28'
AND ItemId = '15'
ORDER BY
JobSequence ASC
When executing the query I get this result
Now I want to add a extra column with this at runtime which will contain status. If the RemainingQty is 0 and CompletedQty is greater than 0 then the status column will contain complete else pending.
Like following picture
Is it possible without a loop?

Sure, no problem - that's a really simple CASE expression:
SELECT
RemainingQty, CompletedQty,
Status = CASE
WHEN RemainingQy = 0 AND CompletedQty > 0
THEN 'Complete'
ELSE 'Pending'
END
FROM
tblJobStatus AS JT
LEFT OUTER JOIN
TBLJOBWORKS AS TJ ON JobWorksId = TaskId
LEFT OUTER JOIN
tblTotalJob AS T ON T.Id = JobID
WHERE
JT.ProductID = '28'
AND ItemId = '15'
ORDER BY
JobSequence ASC

select
...,
case
when RemainingQty = 0 and CompletedQty > 0 then 'Complete'
else 'Pending'
end as Status
from ...

SELECT
RemainingQty, CompletedQty,
case when RamaininQty = and CompletedQty > 0 then 'Complete' else 'Pending' end as Status
FROM
tblJobStatus AS JT
LEFT OUTER JOIN
TBLJOBWORKS AS TJ ON JobWorksId = TaskId
LEFT OUTER JOIN
tblTotalJob AS T ON T.Id = JobID
WHERE
JT.ProductID = '28'
AND ItemId = '15'
ORDER BY
JobSequence ASC

SELECT
RemainingQty, CompletedQty,
Case when RemainingQty=0 and CompletedQty>0 then 'Complete' else 'Pending' end as Status
FROM
tblJobStatus AS JT
LEFT OUTER JOIN
TBLJOBWORKS AS TJ ON JobWorksId = TaskId
LEFT OUTER JOIN
tblTotalJob AS T ON T.Id = JobID
WHERE
JT.ProductID = '28'
AND ItemId = '15'
ORDER BY
JobSequence ASC

Related

add a column to the select query which could be null

I would like to add another column to my select query called description inside posts table,
the problem is that this value could be null.
to make it clear, I have already linked foreign keys from tables Users, PostType and Votes.
Attaching the query:
SELECT po.id,
po.title,
CONVERT(varchar, po.pDate, 104) AS pDate,
pt.type,
us.userName,
SUM(CASE WHEN vt.isLike = 1 THEN 1 ELSE 0 END) AS upvotes,
SUM(CASE WHEN vt.isLike = 0 THEN 1 ELSE 0 END) AS downvotes
FROM Posts po
INNER JOIN PostType pt ON po.typeId = pt.id
INNER JOIN Users us ON po.userId = us.id
LEFT OUTER JOIN Votes vt ON vt.postId = po.id
GROUP BY po.id,
po.pDate,
po.title,
pt.type,
us.userName;
How to avoid group by null?
You can make that column non-nullable on the fly. So in the SELECT clause just add one more column to display CASE WHEN po.description IS NULL THEN 'present' ELSE 'absent' END AS description and repeat it in the GROUP BY clause CASE WHEN po.description IS NULL THEN 'present' ELSE 'absent' END
SELECT po.id,
po.title,
CASE WHEN po.description IS NULL THEN 'present' ELSE 'absent' END AS description,
CONVERT(varchar, po.pDate, 104) AS pDate,
pt.type,
us.userName,
SUM(CASE WHEN vt.isLike = 1 THEN 1 ELSE 0 END) AS upvotes,
SUM(CASE WHEN vt.isLike = 0 THEN 1 ELSE 0 END) AS downvotes
FROM Posts po
INNER JOIN PostType pt ON po.typeId = pt.id
INNER JOIN Users us ON po.userId = us.id
LEFT OUTER JOIN Votes vt ON vt.postId = po.id
GROUP BY po.id,
po.pDate,
po.title,
CASE WHEN po.description IS NULL THEN 'present' ELSE 'absent' END,
pt.type,
us.userName;

Subquery from another table in Case when condition

I am trying to write a query where I want to sum a price column based on the condition which is a subquery.
my query :
select
fund.FundName,
SUM(Case when (
Select Top 1 bitValue
from table 1
where table1.id = Company.id and table1.field = 25
) = 1 then price else 0 end) as 'TotalPrice'
from
Fund left outer join Company on Company.fundId=fund.id
group by
fund.fundName
It throws me error : Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
What is the best alternative way to achieve this.
Hope this Works for your Case:
SELECT
FUND.FUNDNAME,
S.TotalPrice
FROM FUND
LEFT OUTER JOIN COMPANY ON COMPANY.FUNDID=FUND.ID
LEFT JOIN (SELECT CASE WHEN BITVALUE=1 THEN SUM(PRICE) ELSE 0 END as 'TotalPrice',table1.ID
from table 1
where table1.id = Company.id and table1.field = 25 GROUP BY table1.ID
) S ON S.ID=Company.id
GROUP BY
FUND.FUNDNAME
untested obviously with no sample data provided.
select fund.FundName
,SUM(Case when table1.id is not null then price else 0 end) as 'TotalPrice'
from Fund
left outer join Company on Company.fundId = fund.id
left outer join (
select distinct id
from table1
where field = 25
and bitvalue = 1
) table1 on table1.id = Company.id
group by fund.fundName

Why is my query inside of a case when failing?

I'm trying to run a SQL Server Case query and I'm running into an error. Let me try to explain why I'm doing what I'm doing, as well as what I'm looking for in the end result.
I have two Tables. 1 that has an opportunity ID (in this case A.ID) and the second table has accounts with one column I'm interested in (B.Q3ABM__C). What I'm asking SQL to do in this case when is that for every A.id that is null in in the B.Q3ABM__C colum give me a 1, and then again vice versa.
Why is this failing?
SELECT B.ID as Account_ID, B.FULL_ACCOUNT_ID__C, A.ID as Opportunity_ID,A.name, stagename,closedate,A.createddate,
OPPORTUNITY_PRODUCT__C,AMOUNT, B.Q3ABM__C, B.Drip_Campaign_Code__c,OPPORTUNITYTYPE_STRING__C,
CASE
WHEN (SELECT A.id FROM SF_OPPORTUNITY as a
LEFT JOIN SF_ACCOUNT as b on A.Accountid = b.ID where B.Q3ABM__C IS NULL) THEN 1
ELSE 0
END AS 'Does Not Exist in Q3DM',
CASE
WHEN (SELECT A.id FROM SF_OPPORTUNITY as a
LEFT JOIN SF_ACCOUNT as b on A.Accountid = b.ID where B.Q3ABM__C IS NOT NULL) THEN 1
ELSE 0
END AS 'Exists in Q3DM'
FROM SF_OPPORTUNITY as a
LEFT JOIN SF_ACCOUNT as b on a.ACCOUNTID = b.ID
WHERE A.createddate >= '7-1-2019'
AND CLOSEDATE <= '12-31-2019'
Thanks!
If you are selecting records in specific period, but you want to check for NULLs and NOT NULLs for all records, you can check for which ID there are NULL values. If NULL vales exists, then we can calculate the first Does Not Exist in Q3DM column, if not exists the second Exists in Q3DM:
WITH DataSource AS
(
SELECT DISTINCT A.id
FROM SF_OPPORTUNITY as a
LEFT JOIN SF_ACCOUNT as b
on A.Accountid = b.ID
where B.Q3ABM__C IS NULL
)
SELECT B.ID as Account_ID
,B.FULL_ACCOUNT_ID__C
,A.ID as Opportunity_ID
,A.name
,stagename
,closedate
,A.createddate
,OPPORTUNITY_PRODUCT__C
,AMOUNT
,B.Q3ABM__C
,B.Drip_Campaign_Code__c
,OPPORTUNITYTYPE_STRING__C
,CASE DS.Id IS NOT NULL THEN 1 ELSE 0 END 'Does Not Exist in Q3DM'
,CASE DS.Id IS NULL THEN 1 ELSE 0 END 'Exists in Q3DM'
FROM SF_OPPORTUNITY as a
LEFT JOIN SF_ACCOUNT as b
on a.ACCOUNTID = b.ID
LEFT JOIN DataSource DS
ON A.ACCOUNTID = DS.ID
WHERE A.createddate >= '7-1-2019'
AND CLOSEDATE <= '12-31-2019';
If you are interested only in the for the given period and checking the value for the current record only:
SELECT B.ID as Account_ID
,B.FULL_ACCOUNT_ID__C
,A.ID as Opportunity_ID
,A.name
,stagename
,closedate
,A.createddate
,OPPORTUNITY_PRODUCT__C
,AMOUNT
,B.Q3ABM__C
,B.Drip_Campaign_Code__c
,OPPORTUNITYTYPE_STRING__C
,CASE DS.Id IS NULL THEN 1 ELSE 0 END 'Does Not Exist in Q3DM'
,CASE DS.Id IS NOT NULL THEN 1 ELSE 0 END 'Exists in Q3DM'
FROM SF_OPPORTUNITY as a
LEFT JOIN SF_ACCOUNT as b
on a.ACCOUNTID = b.ID
LEFT JOIN DataSource DS
ON A.ACCOUNTID = DS.ID
WHERE A.createddate >= '7-1-2019'
AND CLOSEDATE <= '12-31-2019'
Try this (Use column in 'Select' and 'Where' clause as per your requirements):
SELECT A.*,B.* ,
CASE WHEN B.Q3ABM__C IS NULL THEN 1 ELSE 0 END AS 'DOES NOT EXISIT IN Q3DM',
CASE WHEN B.Q3ABM__C IS NOT NULL THEN 1 ELSE 0 END AS 'EXISITS IN Q3DM'
FROM PLS.SF_OPPORTUNITY A
FULL JOIN PLS.SF_ACCOUNT B ON A.ACCOUNTID=B.ID

T-SQL Aggregate function subquery

I get the following error:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
With this code:
SELECT
loc.Location
,COUNT(CASE
WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'XYZ')
THEN 1
ELSE NULL
END) AS XYZ_Trainee_Count
,COUNT(CASE
WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'ABC')
THEN 1
ELSE NULL
END) AS ABC_Trainee_Count
FROM
dbo.n_HRODS hr INNER JOIN dbo.Locations loc
ON loc.LocationID = hr.LocationID
INNER JOIN dbo.EmpData dat
ON dat.EmpID = hr.EmpID
WHERE dat.Trainee = 1
GROUP BY loc.Location
dbo.[Titles] is a view that combines two columns from two other tables. I'm basically doing it this way because the programmer before me did something like this:
,COUNT(CASE
WHEN SAC in ( lists about 30 items)
THEN 1
ELSE NULL
END)
Obviously, I don't want to list 30 items in that case statement... and when those items change for whatever reason in 3 years, then who's going to remember to go back in this code and updated those items? Nobody...
Thanks in advance for your help.
You can do this with a couple of extra LEFT OUTER JOINs to that title table:
SELECT
loc.Location
,COUNT(CASE WHEN titles1.[SAC] IS NOT NULL THEN 1 ELSE NULL END) AS XYZ_Trainee_Count
,COUNT(CASE WHEN titles2.[SAC] IS NOT NULL THEN 1 ELSE NULL END) AS ABC_Trainee_Count
FROM
dbo.n_HRODS hr INNER JOIN dbo.Locations loc
ON loc.LocationID = hr.LocationID
INNER JOIN dbo.EmpData dat
ON dat.EmpID = hr.EmpID
LEFT OUTER JOIN dbo.[Titles] titles1
ON titles1.[title]='XYZ' AND
hr.SAC = titles1.[SAC]
LEFT OUTER JOIN dbo.[Titles] titles2
ON titles2.[title]='ABC' AND
hr.sac = titles2.[SAC]
WHERE dat.Trainee = 1
GROUP BY loc.Location
Alternatively, if you are really married to those subqueries in your SELECT statement because the actual query is a big nightmare and the thought of monkeying with the joins is enough to make you faint, then you can just remove the aggregation from this query and shove it all into a subquery before aggregation:
SELECT location, count(XYZ_Trainee) AS XYZ_Trainee_Count, count(ABC_Trainee) as ABC_Trainee
FROM
(
SELECT
loc.Location
,CASE
WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'XYZ')
THEN 1
ELSE NULL
END AS XYZ_Trainee
,CASE
WHEN hr.SAC in (SELECT [SAC] FROM dbo.[Titles] WHERE [title] = 'ABC')
THEN 1
ELSE NULL
END AS ABC_Trainee
FROM
dbo.n_HRODS hr INNER JOIN dbo.Locations loc
ON loc.LocationID = hr.LocationID
INNER JOIN dbo.EmpData dat
ON dat.EmpID = hr.EmpID
WHERE dat.Trainee = 1
) sub
GROUP BY location
I would aim for the first solution though since it's going to be easier to maintain and probably get a better execution path from your RDBMS and run quicker as a result. Although... that's just a guess.
Very similar to JNevill first answer. But if you join with title once, you can check and count for any number of title you want.
SELECT
loc.Location
,COUNT(CASE WHEN t.[title] = 'XYZ' THEN 1 END) AS XYZ_Trainee_Count
,COUNT(CASE WHEN t.[title] = 'ABC' THEN 1 END) AS ABC_Trainee_Count
FROM
dbo.[n_HRODS] hr
INNER JOIN dbo.[Locations] loc
ON loc.LocationID = hr.LocationID
INNER JOIN dbo.[EmpData] dat
ON dat.EmpID = hr.EmpID
INNER JOIN dbo.[Titles] t
ON hr.SAC = t.[SAC]
WHERE dat.Trainee = 1
GROUP BY loc.Location

Find combination which does not have 'AC' status

Consider the data below which is stored in temp table. How to get all those ID / State / Group combination which does not have Status record having 'AC' value ?
Data Image
The result should yield
ID State Group
2 FL LI
3 FL VA
5 FL LI
There are several query patterns that will achieve that result.
An example of one of those patterns, using an GROUP BY operation, with aggregation of a condition (to exclude the groupings where there's a row in the grouping that has a status value of 'AC')
SELECT t.id
, t.state
, t.group
FROM mytable t
GROUP
BY t.id
, t.state
, t.group
HAVING MAX(CASE WHEN t.status='AC' THEN 1 ELSE 0 END) = 0
An example of another pattern, using an anti-join:
SELECT t.id
, t.state
, t.group
FROM mytable t
LEFT
JOIN mytable s
ON s.id = t.id
AND s.state = t.state
AND s.group = t.group
AND s.status = 'AC'
WHERE s.id IS NULL
GROUP
BY t.id
, t.state
, t.group
Select *
FROM TableName t
WHERE NOT EXISTS (SELECT 1
FROM TableName
WHERE [State] = t.[State]
AND [Group] = t.[Group]
AND [Status] = 'AC')

Resources