If Statement in SQL From Clause - sql-server

I'm trying to perform an if statement that needs to be done within the From clause of my query. However when I try to do so, I get this error
Incorrect syntax near the keyword 'THEN'.
The query I'm trying to use is the following:
SELECT *
FROM
--a few tables with joins
IF (#a IS NULL OR #a <> '') THEN
--perform a few more joins
WHERE
--rest of query
Is it not possible to perform a case or if statement from the from clause?

After realising I can't use a IF Statement and Case would be more appropriate, I've read up and this can only be done dynamically and not from SQL itself.

You can't do this on a fundamental level. When you write a query, you already know what data it will return and what tables are needed to get that data.
Now, you can do some switchng between tables in a join by using outer joins and statements like ISNULL() and COALESCE() to see if the joined table actually has the data we're looking for.
The joins could loook like this:
declare #checkthis int
select #checkthis = (whatever, resulting in a 1 or a 0)
select *
from tbl_a as a
left outer join tbl_b as b -- tbl_b is optional if #checkthis is 1, else ignore it
on a.b_foreign_key = b.primary_key and #checkthis = 1

Depending on your joins, you can do something like this...
DECLARE #Join AS BIT
SET #Join = 1 --Performs inner join
SET #Join = 0 --ignores join
SELECT *
FROM Table1 a
LEFT JOIN Table2 b
ON a.Id = b.Id
WHERE
((#Join = 0) OR (#Join = 1 AND b.Id IS NOT NULL))

The IF statement in TSQL has the following syntax:
IF [Condition] --NO 'THEN' keyword needed
BEGIN
--myquery
END
ELSE IF [2nd Condition]
BEGIN
--myquery
END
ELSE
BEGIN
--myquery
END
[Condition] can be everything that gives you a TRUE output like
IF DAY(GETDATE()) = 7
BEGIN
PRINT 'IT IS TRUE'
END
ELSE
BEGIN
PRINT 'IT IS FALSE'
END
For your specific problem, you can use CASE statement, in a WHERE clause, like this:
SELECT *
FROM MYTABLE T
INNER JOIN MYTABLE2 T2 ON T2.ID = T1.ID
WHERE T.MYCOLLUMN = CASE
WHEN T.MYCOLUMN2 = 0 THEN 'FIRST'
WHEN T.MYCOLUMN2 = 1 THEN 'SECOND'
ELSE T2.MYCOLUMN
END

Related

Update row with values from select on condition, else insert new row

I'm need to run a calculation for month every day. If the month period, exists already, I need to update it, else I need to create a new row for the new month.
Currently, I've written
declare #period varchar(4) = '0218'
DECLARE #Timestamp date = GetDate()
IF EXISTS(select * from #output where period=#period)
/* UPDATE #output SET --- same calculation as below ---*/
ELSE
SELECT
#period AS period,
SUM(timecard.tworkdol) AS dol_local,
SUM(timecard.tworkdol/currates.cdrate) AS dol_USD,
SUM(timecard.tworkhrs) AS hrs,
#Timestamp AS timestamp
FROM dbo.timecard AS timecard
INNER JOIN dbo.timekeep ON timecard.ttk = timekeep.tkinit
INNER JOIN dbo.matter with (nolock) on timecard.tmatter = matter.mmatter
LEFT JOIN dbo.currates with (nolock) on matter.mcurrency = currates.curcode
AND currates.trtype = 'A'
AND timecard.tworkdt BETWEEN currates.cddate1
AND currates.cddate2
WHERE timekeep.tkloc IN('06','07') AND
timecard.twoper = #period
SELECT * FROM #output;
How can simply update my row with the new data from my select.
Not sure what RDBMS are you using, but in SQL Server something like this would update the #output table with the results of the SELECT that you placed in the ELSE part:
UPDATE o
SET o.dol_local = SUM(timecard.tworkdol),
SET o.dol_USD = SUM(timecard.tworkdol/currates.cdrate),
SET o.hrs = SUM(timecard.tworkhrs),
set o.timestamp = #Timestamp
FROM #output o
INNER JOIN dbo.timecard AS timecard ON o.period = timecard.twoper
INNER JOIN dbo.timekeep ON timecard.ttk = timekeep.tkinit
INNER JOIN dbo.matter with (nolock) on timecard.tmatter = matter.mmatter
LEFT JOIN dbo.currates with (nolock) on matter.mcurrency = currates.curcode
AND currates.trtype = 'A'
AND timecard.tworkdt BETWEEN currates.cddate1
AND currates.cddate2
WHERE timekeep.tkloc IN('06','07') AND
timecard.twoper = #period
Also, I think you want to do an INSERT in the ELSE part, but you are doing just a SELECT, so I guess you should fix that too
The answer to this will vary by SQL dialect, but the two main approaches are:
1. Upsert (if your DBMS supports it), for example using a MERGE statement in SQL Server.
2. Base your SQL on an IF:
IF NOT EXISTS (criteria for dupes)
INSERT INTO (logic to insert)
ELSE
UPDATE (logic to update)

Stored procedure with conditional Where clause in SQL Server

I am creating a SQL Server stored procedure. It's a simple SELECT query that I am building. One of the parameters is to look for a flag parameter. If that parameter is left blank, then the SELECT should default to NOT having the WHERE clause at all.
CREATE PROCEDURE sprocA
#flagInd int
AS
BEGIN
SELECT intID, strQuestion, strAnswer, intCategory, intOrder
FROM tblA
-- Right here is where I am looking for the logic of the #flagInd to be evaluated.....
-- if #flagInd = 1 then 'WHERE flgInd=1'
-- else if #flagInd=0 then 'WHERE flgInd=0'
-- else if #flagInd IS NULL then ''
It's just a simple query and a simple thought I had, not sure if it can be done without nesting and rewriting the whole SELECT statement as part of of the IF statement.
This can be done like:
SELECT intID, strQuestion, strAnswer, intCategory, intOrder
FROM tblA
WHERE flgInd = #flgInd OR #flgInd IS NULL;
You can also use a CASE expression:
SELECT intID, strQuestion, strAnswer, intCategory, intOrder
FROM tblA
WHERE CASE
WHEN flgInd = #flgInd THEN 1
WHEN #flgInd IS NULL THEN 1
ELSE 0
END = 1;
There appears to just be a one to one mapping (from the parameter to the column) so why not use a simple where clause?
CREATE PROCEDURE sprocA
#flagInd int
AS
BEGIN
SELECT intID, strQuestion, strAnswer, intCategory, intOrder
FROM tblA WHERE flgInd = #flagInd;

I am trying to use an IF statement using a select IN clause. What is he correct syntax for the following T-SQL statement?

Using SQL Server 2000; I am trying to determine the action if a value in a field of the INSERTED record matches one of several distinct values in a field in a table. Field y in tableB could be say 'one', 'two' or 'three'. The INSERTED record must be a single record, and therefore the field x must be a single value. Hence, given the code snippet below, what is the correct syntax? In particular where do the "()" go in the IF statement?
if select x from INSERTED in (select y from tableB)
and <another condition>
begin
<some code>
end
The correct syntax is
IF EXISTS (SELECT * FROM TABLE1 WHERE X IN (1,2))
Begin
-- code
End
You can store the individual flag in variables and use that in IF condition.
Declare #chkExist int
Select #chkExist = Count(*) from tableA x in (select y from tableB)
if ((#chkExist > 0) and (<another condition>))
begin
<some code>
end
Try a "where exists" instead of "IN"
if exists ( select null from tableA taAlias where (select null from tableB tbAlias where tbAlias.y = taAlias.x ) )
and 1=1
begin
Select 1 as 'YouNeedAtLeastOneLineOfCodeInThisBeginEnd'
end

SQL INSERT with conditional statement IF THEN ELSE

I am trying to MERGE values from one table to another. One of the values is a conditional value, but it looks like I am not getting the syntax correctly. Initially, I was using an IF-THEN-ELSE statement but was advise to use a CASE statement instead.
Here is the gist the syntax that is failing:
CREATE PROCEDURE EmployeeMerge
AS
BEGIN
SET NOCOUNT ON;
MERGE INTO Employee AS t1
USING
(SELECT
EmployeeName,
Zip,
UpdateDate
FROM table2) AS t2
ON (t1.EmployeeID = t2.EmployeeID)
WHEN MATCHED AND t2.UpdatedDate > t1.UpdatedDate THEN
UPDATE
SET
t1.EmployeeName = s.EmployeeName,
t1.Zip =
(CASE
WHEN t2.ZipExt IS NULL OR t2.ZipExt = '' THEN t2.Zip
ELSE (t2.Zip + '-' + t2.ZipExt)
END),
t1.UpdatedDate = t2.UpdateDate
WHEN NOT MATCHED THEN
INSERT (EmployeeName,
Zip,
ModDate)
VALUES
(t2.Name,
(CASE
WHEN t2.ZipExt IS NULL OR t2.ZipExt = '' THEN t2.Zip
ELSE (t2.Zip + '-' + t2.Zip_Ext)
END),
t2.UpdatedDate)
OUTPUT
deleted.*,
$action,
inserted.*
END; **-- A MERGE statement must be terminated by a semi-colon (;)**
GO
This MERGE statement works just fine if I do not implement the condition, i.e. simply set the t1.Zip = t2.Zip, but of course, this is avoiding the t2.ZipExt field.
A MERGE statement must be terminated by a semi-colon (;)
You haven't terminated the MERGE with a semicolon. You have terminated BEGIN-END. Move the semicolon.
I never really cared for the merge command. There are times where I can see using it, but for the most part, it's more complicated than I like my SQL.
UPDATE e
SET e.EmployeeName=t1.EmployeeName
, e.Zip=CASE
WHEN t1.ZipExt IS NULL OR t1.ZipExt = '' THEN t1.Zip
ELSE (t1.Zip + '-' + t1.ZipExt)
END
, e.UpdatedDate=t1.UpdatedDate
FROM Employee e
INNER JOIN Table t1 ON e.EmployeeID = t1.EmployeeID
WHERE t1.UpdatedDate > e.UpdatedDate
INSERT INTO Employee (EmployeeName,Zip,UpdatedDate)
SELECT
t1.EmployeeName
, t1.Zip=CASE
WHEN t1.ZipExt IS NULL OR t1.ZipExt = '' THEN t1.Zip
ELSE (t1.Zip + '-' + t1.ZipExt)
END
, t1.UpdatedDate
FROM Table t1
LEFT JOIN Employee e ON e.EmployeeID = t1.EmployeeID
WHERE e.EmployeeID IS NULL

Repeating same SQL

I am writing a CASE statement in my SQL Server Stored Procedure. There I am repeeating a same long SQL statements every time for 11 CASEs. Should I put the SQL Statement in CASE condition in a another Stored Procedure? What could be the best approach?
CASE (SELECT ..................)
THEN 'SELCET a.field'
ELSE
''SELECT vlaues'
END
as 'Coulmn1 '
CASE (SELECT ..................)
THEN 'SELCET vaues'
ELSE
''SELECT vlaues'
END
as 'Coulmn1 '
You might want to do something like
SELECT
CASE (your select statement which retuns one value)
WHEN 'option1' THEN 'value2return1'
WHEN 'option2' THEN 'value2return2'
WHEN 'option3' THEN 'value2return3'
...
ELSE 'defaultValue'
END
Use common table expressions link.
WITH CTE (ColA)
AS
(
Select ColA From Table
)
SELECT ColA
FROM CTE
Use a CTE. In the future it would help if you gave us a slightly better example of your code however.
WITH RepeateSelect AS (SELECT ..................)
.....
.....
CASE (SELECT * FROM RepeateSelect)
THEN 'SELCET a.field'
ELSE
'SELECT vlaues'
END
as 'Coulmn1 '
CASE (SELECT * FROM RepeateSelect)
THEN 'SELCET vaues'
ELSE
''SELECT vlaues'
END
as 'Coulmn1 '
Try using the repeated query once thusly:
select A.C1, X.C2, X.C3
from TableA as A inner join
( select B.AlmondJoy,
case when B.YN > 7 then 'Yes' else 'No' end as C2,
case when C.UD in ( -1, 1 ) then 'Up' else 'Down' end as C3
from TableB as B inner join
TableC as C on C.Id = B.Id
) as X on X.AlmondJoy = A.Zagnut

Resources