Write into temp table from two alternate sql statements - sql

I want to write the output of two queries into a table based on a condition. I have this piece of query but does not work. Please advise.
DECLARE #promptflag varchar(1) = 'N';
DECLARE #pool varchar(10) = 'PJMRTO';
IF Object_id('tempdb..#pnode') IS NOT NULL
DROP TABLE #pnode;
select
case when #promptflag='Y' then
(select distinct YES_PNODE from PRICE_NODES where ISO = #pool and Biddable='Y')
when #promptflag='N' then
(select distinct YES_PNODE from PRICE_NODES where ISO = #pool and Biddable='Y' and NonPrompt_Node='Y')
end
INTO #pnode

The idea is more like this:
select distinct YES_PNODE
into #pnode
from PRICE_NODES
where ISO = #pool and Biddable = 'Y' and
(#promptflag = 'Y' or NonPrompt_Node = 'Y');
The or expression is just a shortening of your query logic.

Related

SQL Server Date Comparison issue

I am trying to flag a field in a different table whenever two dates do not have the right relationship. However, All dates in the dataset should not flag anything(should be 0 instead of 1), but they all flag. Could it be an issue with the date format changing during the query? Really stuck here
Example output
UPDATE Theatre_DQ_03_Integrity_CASES
SET AnaesToTheatreFlag = 1, TimeErrorFlag = 1
FROM Theatre_Cases_Landing a
INNER JOIN
(
SELECT Case_ID
FROM Theatre_Cases_Landing
WHERE (CaseCancelled IS NULL or CaseCancelled = 'N') AND (CONVERT(datetime,Anaesthetic_Start_DateTime) > CONVERT(datetime,In_Theatre_DateTime))
AND Anaesthetic_Start_DateTime IS NOT NULL AND In_Theatre_DateTime IS NOT NULL
) b
ON a.Case_ID = b.Case_ID
declare #var1 as datetime2 = '2019-09-04 11:12:00.000'
declare #var2 as datetime2 = '2019-09-04 11:13:00.000'
if #var1 < #var2 PRINT('TRUE')
You need to correlate rows to be updated with the rows from the other table. Otherwise, every row in the target will be updated.
I don't see a need to self-join Theatre_Cases_Landing. Below is an untested version with the correlation.
UPDATE target
SET AnaesToTheatreFlag = 1, TimeErrorFlag = 1
FROM Theatre_DQ_03_Integrity_CASES AS target
JOIN Theatre_Cases_Landing AS a ON a.Case_ID = target.Case_ID
WHERE
(a.CaseCancelled IS NULL or a.CaseCancelled = 'N')
AND CONVERT(datetime,a.Anaesthetic_Start_DateTime) > CONVERT(datetime,a.In_Theatre_DateTime)
AND a.Anaesthetic_Start_DateTime IS NOT NULL
AND a.In_Theatre_DateTime IS NOT NULL;

Use variable sql for column name

Before you shout at me in CAPS for not searching - I have! Dynamic SQL is good, dynamic SQL is bad. Learning a lot..
I can accomplish what I'm after by using logic in there WHERE clause, but it adds a significant amount of run time. The query takes 8 seconds if I hard code the criteria and 1:20 if I use the WHERE logic.
Here is what I'd like to do:
Declare #EmployeeToggle varchar(30)
Declare #Employee_ID varchar(30)
Declare #EmployeeField varchar(100)
set #EmployeeToggle = '1'
set #Employee_ID = '1166'
set #EmployeeField = case when #EmployeeToggle = '1' then 'Field1' else
'Field2' end;
select * from Table1 where #EmployeeField = #Employee_ID
I don't think it's possible without dynamic sql. I still don't know whether or not I should use it. It's my thought that it would take the query back down to 8 seconds, because it would immediately know which field to use in the where clause.
Alternatively, a few ways to do it in the where only:
where (( not #EmployeeToggle = '1') or Field1 = #Employee_ID) and
(#EmployeeToggle = '1' or Field2 = #Employee_ID)
where (1=(case when #EmployeeToggle = '1' then 1 else 0 end ) or Field1 =
#Employee_ID)
and (1=(case when #EmployeeToggle = '2' then 1 else 0 end) or Field2 =
#Employee_ID)
These work great (admittedly I copied and pasted these examples), but at the expense of run time.
My final thought, and the way others have done it at my org, is to create two scripts that are identical except for the field used in the where clause. So, if #EmployeeToggle = '1' it will run the first script and if it's '2' it will run the second. I haven't tried that yet, but I assume the runtime will be closer to the 8 seconds at the expense of some ugly code.
Thanks for the help.
Why not just use a single query?
select t.*
from table1
where #EmployeeToggle = '1' and field_1 = #Employee_ID
union all
select t.*
from table1
where #EmployeeToggle <> '1' and field_2 = #Employee_ID;
By using union all, SQL Server should use indexes for each subquery -- and if you have indexes on the fields, the query should be fast.
You can stay with static SQL when using CASE expression in SELECT then filter it.
SELECT *
FROM (
SELECT *,
CASE WHEN #EmployeeToggle = '1' THEN Field1 ELSE Field2 END AS Field1_2
FROM Table1
) t
WHERE
Field1_2 = #Employee_ID
Here is your dynamic query:
Declare #EmployeeToggle varchar(30)
Declare #Employee_ID varchar(30)
Declare #EmployeeField varchar(100)
set #EmployeeToggle = '1'
set #Employee_ID = '1166'
set #EmployeeField = case when #EmployeeToggle = '1' then 'Field1' else
'Field2' end;
DECLARE #SQLString VARCHAR(MAX)
SET #SQLString='select *
from Table1
where '+#EmployeeField+' = '+#Employee_ID+''
PRINT(#SQLString) --If you want to check actual query
EXEC(#SQLString)

Apply and/or in SQL query based on flags passed to stored procedure

I need a query which can apply and/or clauses dynamically basing on the flags. I am using SQL Server 2014.
Consider the following example:
declare #UGFlag char(1)
declare #PGFlag char(1)
declare #DoctrateFlag char(1)
create table #FiltQual(Candidate_ID int) -- Final Output
create table #FiltUG(Candidate_ID int)
create table #FiltPG(Candidate_ID int)
create table #FiltDOC(Candidate_ID int)
insert into #FiltUG
select '1' union
select '2' union
select '3'
insert into #FiltPG
select '1' union
select '2'
insert into #FiltPG
select '2' union
select '3' union
select '4' union
select '5'
--Case 1
set #UGFlag='Y'
set #PGFlag='Y'
set #DoctrateFlag = 'Y'
--Desired Output
Candidate_ID
2
Case 2
set #UGFlag='N'
set #PGFlag='N'
set #DoctrateFlag = 'N'
Desired Output
Candidate_ID
1
2
3
4
5
Case 3:
set #UGFlag='N'
set #PGFlag='Y'
set #DoctrateFlag = 'N'
Desired Output
Candidate_ID
1
2
Case 4:
set #UGFlag='Y'
set #PGFlag='Y'
set #DoctrateFlag = 'N'
Desired Output
Candidate_ID
1
2
I want to populate data into #FiltQual basing on the trhee flags. Flags can contain either 'Y' or 'N', if it is 'Y' then 'And' should be apllied else 'or' should be applied.
Something like this should work:
SELECT COALESCE(UG.Candidate_ID, PG.Candidate_ID, DOC.Candidate_ID) AS Candidate_ID
FROM #FiltUG AS UG
FULL OUTER JOIN #FiltPG AS PG ON UG.Candidate_ID = PG.Candidate_ID
FULL OUTER JOIN #FiltDOC AS DOC ON PG.Candidate_ID = DOC.Candidate_ID
WHERE ((#UGFlag='Y' AND UG.Candidate_ID IS NOT NULL) OR (#UGFlag='N'))
AND
((#PGFlag='Y' AND PG.Candidate_ID IS NOT NULL) OR (#PGFlag='N'))
AND
((#DoctrateFlag='Y' AND DOC.Candidate_ID IS NOT NULL) OR (#DoctrateFlag='N'))
The key idea is to use a FULL JOIN between all tables. Then using, for example:
(#UGFlag='Y' AND UG.Candidate_ID IS NOT NULL) OR (#UGFlag='N')
we apply the NOT NULL condition to a table (#FiltUG) if the corresponding table filter (#UGFlag) is equal to 'Y.
Demo here
Not a complete answer, but the following abstract pattern can work. What you do is stack a check for the condition indicator in with the actual check.
SELECT *
FROM Table
WHERE (#ConditionIndicator = 'Y' AND (Column = #Value))
A slightly more concrete example, that does not address your sample data:
DECLARE #Filter NCHAR(1);
SET #Filter = 'Y'; -- Change to 'N' (or anything other than 'Y') to see the results change
SELECT *
FROM sysobjects
WHERE (#Filter = 'Y' AND name = 'sysrscols')
When #Filter == 'Y', it returns 1 row. When #Filter is anything other than 'Y', it returns no rows.
Hope this helps.
Edited to add:
Sorry, just re-read your question. You need something more like the below, but it effectively uses the same pattern:
DECLARE #Filter NCHAR(1);
SET #Filter = 'Y';
SELECT *
FROM sysobjects
WHERE (#Filter = 'Y' AND (name = 'sysrscols' AND xtype = 'S'))
OR (#Filter != 'Y' AND (name = 'sysrscols' OR xtype = 'S'))

Conditional SQL statement - conditioning on column to be returned

I'm trying to make a conditional select statement, and the parameter I'm conditioning on is the column I want to return. Meaning - if something about a column in a table is true, I want to return that column; if not, I want to return the other column.
Ex:
IF table.obj_param_A = ?
BEGIN
SELECT obj_param_A FROM table
END
ELSE
BEGIN
SELECT obj_param_B FROM table
END
I know this doesn't work, but it's the general idea of what I want. Any idea how to structure this properly?
If you do not concern the column name returned, you can use CASE
SELECT
CASE
WHEN obj_param_A = ? THEN obj_param_A
ELSE obj_param_B
END AS value
FROM table
Below is an example of how you can use the table information about a specific column in order to select from specific columns.
Drop Table dbo.Test
Create Table dbo.Test (iVersion int, iVersion2 smallmoney)
Insert Into dbo.Test
Select 1, 1.12
Declare #Test as nvarchar(200)
Select #Test = Column_Name from information_schema.columns where Table_Schema = 'dbo' and table_name = 'test' and Ordinal_Position = 1
--IF (#Test = 'iVersion') --Equal To iVersion
IF (#Test != 'iVersion') ---Not Equal To iVersion
BEGIN
SELECT iVersion FROM dbo.Test
END
ELSE
BEGIN
SELECT iVersion2 FROM dbo.Test
END
This should return the data from iVersion2 since the Name of the First column is "iVersion" and the If Statement returns iVersion only if it is not the first column

Querying different table based on a parameter

I have a stored procedure that I would like to query either the production or the "work in progress" table, based on the parameter I am passing in. I could write two separate stored procedures, but I thought this was worth a try.
something along the lines of:
create procedure getUserDetails
#userID int,
#prod varchar(5)
as
begin
select * from
if (#prod = 'true')
Begin
userprod_table
else
userwip_table
end
where something = 'something'
END
Is this at all possible? I wouldn't want to write 2 SP that are almost identical :-/
Why not use a simple if(#prod = 'true') statement like below:
if (#prod = 'true')
begin
select * from userprod_table where something = 'something'
end else
begin
select * from userwip_table where something = 'something'
end
You could use a CTE so that your main query isn't repeated
with usertable as
(
select * from userprod_table where 1 = #flag
union
select * from userwip_table where 0 = #flag
)
select ... from usertable ...