How to use a query-results in the same Select statement? - sql-server

In my select statement I calculate some values and then need to calculate a new value based on the results of the already calculated values. How can this be archived without using a temp table?
SELECT
CASE WHEN [Customer] = '173220000' THEN '1' ELSE NULL END AS Ver_a
, CASE WHEN [Service] = '173220000' THEN '1' ELSE NULL END AS Ver_b
, CASE WHEN [Productavailability] = '173220000' THEN '1' ELSE NULL END AS Ver_c
, (SUM(Ver_a, Ver_b, Ver_c)/3) AS Identity_Ver
FROM x

Just use a sub-query/derived table:
SELECT
Ver_a
, Ver_b
, Ver_c
, (coalesce(Ver_a,0) + coalesce(Ver_b,0) + coalesce(Ver_c,0))/3 AS Identity_Ver
FROM (
SELECT
CASE WHEN [Customer] = '173220000' THEN '1' ELSE NULL END AS Ver_a
, CASE WHEN [Service] = '173220000' THEN '1' ELSE NULL END AS Ver_b
, CASE WHEN [Productavailability] = '173220000' THEN '1' ELSE NULL END AS Ver_c
FROM x
) x
Note 1: as you are not grouping you don't need the sum function, just the sum operator (+) - and the sum function doesn't take a comma separated list of values either.
Note 2: your sum won't work without using the coalesce function as you are returning null from the case expressions.

Firstly, you cannot do sum(var1, var2, var3).
The answer to your question, as stated, seems to be the code at the end.
BUT, I have to ask: what do you want to accomplish? Your approach does make sense to me :-(
SELECT
Sum(
CASE WHEN [customer] = '173220000' THEN 1 ELSE 0 END +
CASE WHEN [service] = '173220000' THEN 1 ELSE 0 END +
CASE WHEN [productavailability] = '173220000' THEN 1 ELSE 0 END
) / 3 AS Identity_Ver
FROM x

Related

SQL - Alias in CASE statements

I have this piece of code (please look below). I keep getting error: "Invalid column name 'SuppFinish2'
SELECT
CASE
WHEN [RegFinish] IS NULL THEN ''
ELSE [RegFinish]
END AS [RegFinish],
CASE
WHEN [SuppFinish] IS NULL THEN ''
ELSE [SuppFinish]
END AS [SuppFinish2],
CASE
WHEN [RegFinish]<[SuppFinish2] THEN '1'
ELSE '0'
END AS [TEST]
FROM TABLE
Is it because of [SuppFinish2] being an alias? Thanks!
As you said its due to alias and aliased columns can be referenced only on order by to logical query flow order
with cte
as
(
SELECT
CASE
WHEN [RegFinish] IS NULL THEN ''
ELSE [RegFinish]
END AS [RegFinish],
CASE
WHEN [SuppFinish] IS NULL THEN ''
ELSE [SuppFinish]
END AS [SuppFinish2]
FROM TABLE
)
select
CASE
WHEN [RegFinish]<[SuppFinish2] THEN '1'
ELSE '0'
END AS [TEST]
from cte
You cant use those aliases in the same level as you created them, becuase they are not existing yet.. wrap your query with another select like this:
SELECT * ,
CASE
WHEN [RegFinish]<[SuppFinish2] THEN '1'
ELSE '0'
END AS [TEST]
FROM (
SELECT
[ID],
CASE
WHEN [RegFinish] IS NULL THEN ''
ELSE [RegFinish]
END AS [RegFinish],
CASE
WHEN [SuppFinish] IS NULL THEN ''
ELSE [SuppFinish]
END AS [SuppFinish2],
FROM TABLE)
In order to reference aliased columns, you can use a derived table (or CTE, but that is not shown here)
Select *, CASE
WHEN [RegFinish]<[SuppFinish2] THEN '1'
ELSE '0'
END AS [TEST] From
(
SELECT
CASE
WHEN [RegFinish] IS NULL THEN ''
ELSE [RegFinish]
END AS [RegFinish],
CASE
WHEN [SuppFinish] IS NULL THEN ''
ELSE [SuppFinish]
END AS [SuppFinish2]
) T1
FROM TABLE
You cannot, at the same time, set and access an alias in the SELECT clause. I would suggest rewriting your query using CROSS APPLY:
SELECT t1.[RegFinish],
t2.[SuppFinish],
CASE
WHEN t1.[RegFinish] < t2.[SuppFinish] THEN '1'
ELSE '0'
END AS [TEST]
FROM TABLE
CROSS APPLY (SELECT COALESCE([RegFinish], '') AS [RegFinish]) AS t1
CROSS APPLY (SELECT COALESCE([SuppFinish], '') AS [SuppFinish]) AS t2
SELECT ISNULL([RegFinish],'') as [RegFinish]
, ISNULL([SuppFinish],'') as [SuppFinish2], CASE
WHEN
ISNULL([RegFinish],'') < ISNULL([SuppFinish],'') THEN 1
ELSE 0
END AS [TEST]
FROM TABLE
Why not use ISNULL instead of CASE? The problem with your query is that [SuppFinish2] is an alias not an column and can only be used in ORDER BY clause

SQL Server TSQL - How to achieve "NOT IN" statements within a CASE

I have the following working code:
INSERT INTO #resultado
SELECT 1,
v.idReqVoucher,
v.dtSolicitacao,
v.idFuncionario_solicitante,
v.idFuncionario_beneficiario,
v.idStatus,
NULL as valor
FROM reqVoucher v
WHERE
v.idReqVoucher =
CASE WHEN #idRequisicao = 0 THEN v.idReqVoucher
ELSE #idRequisicao END
AND v.idStatus =
CASE WHEN #status = 0 THEN v.idStatus
ELSE #status END
AND v.dtSolicitacao >= CASE WHEN #dtSolicitacaoIni IS NULL THEN v.dtSolicitacao ELSE #dtSolicitacaoIni END
AND v.dtSolicitacao <= CASE WHEN #dtSolicitacaoFim IS NULL THEN v.dtSolicitacao ELSE #dtSolicitacaoFim+' 23:59:59' END
But what I need to achieve is something like that:
AND v.idStatus
CASE WHEN #status = 99 THEN NOT IN (5,1,4,20)
ELSE WHEN #status != 0 THEN = #status END
And I have no idea on how achieve that in my code. I'm fairly new in TSQL and SQL Server, so please be gentle.
Or use a CASE expression:
and case
when #status = 99 and v.idStatus not in ( 5, 1, 4, 20 ) then 1
when #status !=0 and v.idStatus = #status then 1
else 0
end = 1
The CASE expression returns a value which you must then use, e.g. by comparing it to 1. It is generally good practice to include an ELSE clause to supply a default value should the unexpected arise.
The CASE statement returns a value, it does not act as an IF statement by changing the SQL query (if this, then do that). You would need to modify your where statement to something like the following:
AND (
(#status = 99 AND v.idStatus NOT IN (5, 1, 4, 20))
OR (#status NOT IN (0, 99) AND v.idStatus = #status)
)
Edit: Commenter is correct, the 2nd check needs to ensure the #status is not 99.
This should be equivalent to what you want:
AND (
(#status = 99) AND (v.idStatus NOT IN (5,1,4,20))
OR
(#status <> 99) AND (#status <> 0) AND (v.idStatus = #status)
)
CASE expression can only be used to return a scalar value, so it cannot be used to return a predicate like NOT IN (5,1,4,20).

How to retrieve only those column from a table corresponding to which a particular value is present in other column in another table in sql query

I have two tables in a database ,namely main.vacuum_status and main_vacuum_analog. **
logtime is a common field
of both the tables.
In main.vacuum_status there are column namely and st1_vs1_bag1_onoff..in this way there are eight columns upto st1_vs1_bag8_onoff.Some of these columns have 0 or 1 as a value respectively.In another table there are columns st1_vs1_bag1_rb till st1_vs1_bag8_rb with some real type values.
Condition
Now I want a sql query which check whenever there is 1 in st1_vs1_bag1_onoff.. columns then the real type values of another table column st1_vs1_bag1_rb...should be dispalyed.i.e if st1_vs1_bag8_onoff is 0 then st1_vs1_bag8_rb should not be displayed and if st1_vs1_bag8_onoff is 1 then the value of st1_vs1_bag8_rb sholud be displayed.
Is there any such sql query??
EDIT 1
By looking at the answers ,I formed my sql query as
select
case when a.st1_vs1_bag1_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag1_rb ELSE 'Value when 0' END as st1_vs1_bag1_rb ,
CASE when a.st1_vs1_bag2_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag2_rb else '0' END as st1_vs1_bag1_rb ,
CASE when a.st1_vs1_bag3_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag3_rb else '0' END as st1_vs1_bag1_rb ,
CASE when a.st1_vs1_bag4_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag4_rb else '0' END as st1_vs1_bag1_rb ,
CASE when a.st1_vs1_bag5_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag5_rb else '0' END as st1_vs1_bag1_rb ,
CASE when a.st1_vs1_bag6_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag6_rb else '0' END as st1_vs1_bag1_rb ,
CASE when a.st1_vs1_bag7_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag7_rb else '0' END as st1_vs1_bag1_rb ,
CASE when a.st1_vs1_bag8_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag8_rb else '0' END as st1_vs1_bag1_rb ,
from main_vacuum_status a INNER JOIN main_vacuum_analog c ON a.LOGTIME = c.LOGTIME
But error is being shown Incorrect syntax near form
Based on the information you provided, you could do something like the following :
SELECT
CASE WHEN st1_vs1_bag1_onoff = 1 THEN st1_vs1_bag1_rb END AS st1_vs1_bag1_rb
CASE WHEN st1_vs1_bag2_onoff = 1 THEN st1_vs1_bag2_rb END AS st1_vs1_bag2_rb
CASE WHEN st1_vs1_bag3_onoff = 1 THEN st1_vs1_bag3_rb END AS st1_vs1_bag3_rb
CASE WHEN st1_vs1_bag4_onoff = 1 THEN st1_vs1_bag4_rb END AS st1_vs1_bag4_rb
CASE WHEN st1_vs1_bag5_onoff = 1 THEN st1_vs1_bag5_rb END AS st1_vs1_bag5_rb
CASE WHEN st1_vs1_bag6_onoff = 1 THEN st1_vs1_bag6_rb END AS st1_vs1_bag6_rb
CASE WHEN st1_vs1_bag7_onoff = 1 THEN st1_vs1_bag7_rb END AS st1_vs1_bag7_rb
CASE WHEN st1_vs1_bag8_onoff = 1 THEN st1_vs1_bag8_rb END AS st1_vs1_bag8_rb
FROM main_vacuum_status S
INNER JOIN main_vacuum_analog A
ON S.logtime = A.logtime
if st1_vs1_bag*_onoff is different than 1, st1_vs1_bag*_rb will be NULL.
If you want to display a default value instead, put it in the ELSE part, like this :
CASE WHEN st1_vs1_bag1_onoff = 1 THEN st1_vs1_bag1_rb ELSE 'Value when 0' END AS st1_vs1_bag1_rb
You can do the following :
SELECT LOGTIME
,
,CASE
WHEN st1_vs1_bag1_onoff = 1
THEN st1_vs1_bag1_rb
ELSE '<No Value>'
END AS st1_vs1_bag1_rb
,
.
.
.
.
.
.
,CASE
WHEN st1_vs1_bag8_onoff = 1
THEN st1_vs1_bag8_rb
ELSE '<No Value>'
END AS st1_vs1_bag8_rb
FROM main.vacuum_status AL1
INNER JOIN main_vacuum_analog AL2 ON AL1.LOGTIME = AL2.LOGTIME
Let me know if this is not what you are looking for.
I got what I wanted through this query,both the above answers were helpful:))
select c.LOGTIME,
case when a.st1_vs1_bag1_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag1_rb ELSE '0' END as st1_vs1_bag1_rb ,
CASE when a.st1_vs1_bag2_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag2_rb else '0' END as st1_vs1_bag2_rb ,
CASE when a.st1_vs1_bag3_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag3_rb else '0' END as st1_vs1_bag3_rb ,
CASE when a.st1_vs1_bag4_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag4_rb else '0' END as st1_vs1_bag4_rb ,
CASE when a.st1_vs1_bag5_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag5_rb else '0' END as st1_vs1_bag5_rb ,
CASE when a.st1_vs1_bag6_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag6_rb else '0' END as st1_vs1_bag6_rb ,
CASE when a.st1_vs1_bag7_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag7_rb else '0' END as st1_vs1_bag7_rb ,
CASE when a.st1_vs1_bag8_onoff='0' and a.logtime=c.logtime then c.st1_vs1_bag8_rb else '0' END as st1_vs1_bag8_rb
from main_vacuum_status a INNER JOIN main_vacuum_analog c ON a.LOGTIME = c.LOGTIME and
c.logtime between '2014-10-10 07:17:00' and '2014-10-10 08:46:00'

T-SQL - Assign field to NULL in a case statement

Probably am going crazy, but I am trying to assign a field to NULL in a case statement, however, I get an error on the equals next to the NULL keyword
Here is the SQL:
SELECT CASE WHEN enq.IntField = 0 THEN enq.IntField = NULL ELSE enq.IntField END As IntField
FROM [Table]
Surely I am doing something stupid!!
Thanks in advance
Try this
CASE WHEN enq.IntField = 0 THEN NULL ELSE enq.IntField END

determine if any values are null, if true then false, else true

I currently have a select statement that checks several columns to see if they have data. if any of them are null then i want a bit set to false. if none of them are null then i want a bit set to true. here's what i currently have:
select
cast(
case when ChangeOrderNumber is null then 0 else 1 end *
case when ClientName is null then 0 else 1 end *
case when QuoteNumber is null then 0 else 1 end *
case when ClientNumber is null then 0 else 1 end *
case when ServiceLine is null then 0 else 1 end *
case when ServiceLineCode is null then 0 else 1 end *
case when GroupLeader is null then 0 else 1 end *
case when CreatedBy is null then 0 else 1 end *
case when PTWCompletionDate is null then 0 else 1 end *
case when BudgetedHours is null then 0 else 1 end *
case when BudgetDollars is null then 0 else 1 end *
case when InternalDeadlineDate is null then 0 else 1 end *
case when ProjectDescription is null then 0 else 1 end *
case when Sales is null then 0 else 1 end *
case when Coop is null then 0 else 1 end *
case when PassThrough is null then 0 else 1 end *
case when POStatus is null then 0 else 1 end *
case when PONumber is null then 0 else 1 end as bit
)
as Flag
from t
now, that code works, but it's a bit lengthy, i was wondering if anyone knew of a better way to do this. please note that there are several data types being checked.
further details:
this code is in a view that is being looked at in an application for processing change orders. before a change order can be processed it must meet some data quality checks. this view shows if any of the required data is null.
Just add them up since NULL + "something" is always NULL ...
CREATE TABLE #test(column1 int,column2 varchar(4),column3 float)
INSERT #test VALUES(2,'2',2)
INSERT #test VALUES(0,'1',0)
INSERT #test VALUES(null,'1',0)
INSERT #test VALUES(1,null,0)
INSERT #test VALUES(0,'1',null)
INSERT #test VALUES(null,null,null)
SELECT CASE
WHEN column1 + column2 + column3 is NULL THEN 0 ELSE 1 END, *
FROM #test
from a post I created over 3 years ago ...
Keep in mind that if you have characters that are not numbers that you have to convert to varchar ...
INSERT #test VALUES(0,'abc',null)
Here is the conversion, no need to convert the varchar columns
SELECT CASE WHEN CONVERT(VARCHAR(100),column1)
+ column2
+CONVERT(VARCHAR(100),column3) is NULL THEN 0 ELSE 1 END,*
FROM #test
I think I might go with this solution unless someone comes up with a better one, inspired by #Alireza:
cast(
case when (ChangeOrderNumber is null or
a.ClientName is null or
a.QuoteNumber is null or
ClientNumber is null or
ServiceLine is null or
ServiceLineCode is null or
GroupLeader is null or
CreatedBy is null or
PTWCompletionDate is null or
BudgetedHours is null or
BudgetDollars is null or
InternalDeadlineDate is null or
ProjectDescription is null or
Sales is null or
Coop is null or
PassThrough is null or
POStatus is null or
PONumber is null) then 'false' else 'true'
end as bit) as Flag
Please use IIF() (need to be sql server 2012 or later) I really recommend:
IIF(column1 is null, '0', '1')
What about this one?
select not(a is null or b is null or ...)
You could invert the logic.
SELECT
CASE WHEN ChangeOrderNumber IS NOT NULL
AND ClientName IS NOT NULL
AND QuoteNumber IS NOT NULL
....
THEN 1
ELSE 0
END [Flag]
FROM t
Create a HasValue function that takes in a sql_variant and returns a bit. Then use bitwise AND in your SELECT clause.
CREATE FUNCTION dbo.HasValue(#value sql_variant) RETURNS bit
AS
BEGIN
RETURN (SELECT COUNT(#value))
END
GO
SELECT dbo.HasValue(ChangeOrderNumber)
& dbo.HasValue(ClientName)
& dbo.HasValue(QuoteNumber)
...
as [Flag]
FROM t
Or this:
declare #test1 char(1)
declare #test2 char(1)
declare #outbit bit
set #test1 = NULL
set #test2 = 'some value'
set #outbit = 'True'
select #test1
select #test2
If #test1 + #test2 IS NULL set #outbit = 'False'
Select #outbit
Much simpler -- just use the COALESCE function, which returns the value in the first non-null column.
SELECT Flag = CASE
WHEN COALESCE (column1, column2, column3, ...) IS NULL THEN 0
ELSE 1
END
FROM MyTable

Resources