SQL Select all if parameter is empty - sql

I'm looking for a solution that allow me select all records in a
column if the parameter is empty. (see where clause section).
The empty parameters are in the Tempdb and I can't create Store Procedures.
SELECT
DB_NAME(),
ST.ID,
ST.DESC,
SP.DESC,
TF.STARTDATE,
TF.TERMDate
FROM STANDA ST --1st DB -can't create procedures
LEFT JOIN TABLEFEE TF ON TF.TABLEFEE = ST.ID --1st DB -can't create procedures
LEFT JOIN SPECIAL SP ON SP.SPECIALC = TF.SPECIALC --1st DB -can't create procedures
-- EACH FILTER SHOULD SELECT ALL IF PARAMETER IS EMPTY IN THE BELOW SELECT STATEMENT ENCLOSED WITH
((SELECT...))
WHERE ST.DESC IN
((SELECT ME_Desc FROM ##ME_DATA WHERE ME_ID = ##Counter)) --##ME_DATA 2nd DB (temp)
AND SP.DESC IN
((SELECT ME_Special FROM ##ME_DATA WHERE ME_ID = ##Counter))
AND TF.STARTDATE IN
((SELECT ME_STARTDate FROM ##ME_Data WHERE ME_ID = ##Counter))
AND TF.TERMDATE IN
((SELECT ME_TERMDate FROM ##ME_Data WHERE ME_ID = ##Counter))

You can do something like this
(SELECT ME_Desc FROM ##ME_DATA WHERE ME_ID = ##Counter OR ##Counter IS NULL)
Although where you use "IS NULL" may depend on exactly what the data type of ##Counter is ... you say "empty", but potentially it could be a numeric value that will either be zero or a valid number - therefore OR ##Counter = 0 might be more applicable. Also, you haven't specified exactly which database platform you are using, so you should be able to adapt the syntax as required for your situation, if necessary.
Alternatively:
WHERE (
##Counter IS NULL
OR
(ST.DESC IN
((SELECT ME_Desc FROM ##ME_DATA WHERE ME_ID = ##Counter)))
)

Related

Converting a delete statement into a where clause, T-sql

I have removed rows from a results table after it has been built already. I have decided to try to remove the rows from being inserted into the results table in the first place instead.
To remove the appropriate rows from the results table after the fact I used:
if #InterchangeAction = 'HCR'
begin
--Do not allow claims to be output if they have a prior submission marked 'output'
--and the interchange 'output submission action' is marked as 'hold'
delete from #ResultSet
where exists ( select 1 from ClaimSubmissions CS inner join InterchangeInfo I on CS.InterchangeId = I.InterchangeId
where #ResultSet.ClaimId = CS.ClaimId
and CS.InterchangeId = #InterchangeID
and CS.SubmissionStatus = 'OPT'
and CS.OutputDate is not NULL
)
end
This works as I want but I am thinking it would be more efficient to stop the rows from being added in the first place.
I'm going to start my check with:
if #InterchangeAction = 'HCR'
and then concatenate on to the existing where clause but I am unsure on how to convert the delete statement into a where clause?
Any pointers on where to start would be greatly appreciated.
Unless I'm missing something obvious, aren't you just looking for this?:
INSERT #ResultSet
(<Column List>)
SELECT
<Column List>
FROM
WhatHaveYou AS WHY
WHERE NOT EXISTS ( select 1 from ClaimSubmissions CS
inner join InterchangeInfo I
on CS.InterchangeId = I.InterchangeId
where WHY.ClaimId = CS.ClaimId
and CS.InterchangeId = #InterchangeID
and CS.SubmissionStatus = 'OPT'
and CS.OutputDate is not NULL
)

How to write a row that is empty to a Table Variable

I have the following SQL query
Declare #EIDDetail Table
(inc_synopsis varchar(5000),EmployeeName varChar(50),inc_id int, acc_id int
,acc_eid int, inc_event_Number Varchar(12), inc_date_occurred_startdate,acc_afg_id int,
inc_time_occurred_start varchar(8),inc_date_recvd date,inc_date_closed date,inc_is_uof bit,
InvestigatorName VarChar(42),inc_is_comp_via_sup bit,
inc_is_comp_via_psdbit, inc_is_admin_review bit
, inc_comp_is_inquiry bit, inc_comp_is_invest bit, div_name VarChar(50), inc_comp_is_referral bit)
INSERT INTO #EIDDetail SELECT b.inc_synopsis, a.EmployeeName As AccusedName, b.inc_id, a.acc_id, a.acc_eid,
b.inc_event_number, b.inc_date_occurred_start, a.acc_afg_id, b.inc_time_occurred_start, b.inc_date_recvd, b.inc_date_closed, b.inc_is_uof,
c.InvestigatorName, b.inc_is_comp_via_sup, b.inc_is_comp_via_psd,b.inc_is_admin_review,b.inc_comp_is_inquiry,b.inc_comp_is_invest, d.div_name,
b.inc_comp_is_referral
FROM dbo.VW_ACCUSED_DISCIPLINABLE_CHARGE AS a INNER JOIN
dbo.Tbl_Incident AS b ON a.acc_inc_id = b.inc_id LEFT OUTER JOIN
dbo.VW_INCIDENT_INVESTIGATOR AS c ON b.inc_id = c.inc_id LEFT OUTER JOIN
dbo.Tbl_Division AS d ON b.inc_inv_div_id = d.div_id
WHERE
a.acc_eid IN (435,35) And (b.inc_comp_is_inquiry = 'False') AND (b.inc_deleted = 'False') OR
a.acc_eid IN (435,35) And(b.inc_deleted = 'False') AND (b.inc_comp_is_invest = 'False') OR
a.acc_eid IN (435,35) And(b.inc_deleted = 'False') AND (b.inc_comp_is_referral = 'False') OR
a.acc_eid IN (435,35) And(b.inc_deleted = 'False') AND (b.inc_is_uof = 'True')
select * from #EIDDetail
This works okay until I have a parameter that has no records. When That Happens I need to include that employee identified by the parameter and show in the record set the employee name and "No Records Found' in my synopsis field.
I can not seem to figure this out. I have tried using the ISNULL function like this
SELECT ISNULL((SELECT My code above)), (new select here))
But that gives me an error message "Only one expression can be specified in the select list when the subquery is not introduced with EXISTS."
Am I heading in the right direction with the ISNUll function or is there any other way to accomplish this
I'd do something like:
DECLARE #EIDDetail Table <etc>
INSERT INTO #EIDDetail
SELECT <etc>
IF ##rowcount = 0
INSERT INTO #EIDDetail
SELECT <query designed for "no data available" parameters>
Just because it is possible to jam everything into a single query (something I am guilty of myself) doesn't make it a good idea.
If you want to use the ISNULL expression, then you have to use it on that one particular field (not a whole select statement). So, you could have something like:
SELECT ISNULL(field1, "Empty") AS field1, ISNULL(field2, "Empty") AS field 2
FROM TableName
The above assumes that Field1 and field2 are string-types (e.g., Varchar).
The output of your query then should be a left join or outer apply where your primary table is the list of IDs that you passed in (either in flex parameter or a table variable form), so:
SELECT IDs.ID, ISNULL(Records.A, "No Data Available")[, ...n]
FROM #TableOfIDs IDs
OUTER APPLY (
<query returning results you are interested in>
WHERE IDs.ID = InnerIDTable.ID
) Records
Then, on the report side, make your outputs responsive to the first occurrence of "No Data Available" so that it reformats the output. As the point above is made, ensure that your output from ISNULL is the same type as the column you're selecting.

How to update a table if values of the attributes are contained within another table?

I've got a database like this one:
I'm trying to create a query that would enable me to update the value of the status attribute inside the incident table whenever the values of all of these three attributes: tabor_vatrogasci, tabor_policija, and tabor_hitna are contained inside the izvještaj_tabora table as a value of the oznaka_tabora attribute. If, for example, the values of the tabor_vatrogasci, tabor_policija, and tabor_hitna attributes are 3, 4 and 5 respectively, the incident table should be updated if (and only if) 3, 4, and 5 are contained inside the izvještaj_tabora table.
This is what I tried, but it didn't work:
UPDATE incident SET status='Otvoren' FROM tabor,izvjestaj_tabora
WHERE (incident.tabor_policija=tabor.oznaka
OR incident.tabor_vatrogasci=tabor.oznaka
OR incident.tabor_hitna=tabor.oznaka)
AND izvjestaj_tabora.oznaka_tabora=tabor.oznaka
AND rezultat_izvjestaja='Riješen' AND
((SELECT EXISTS(SELECT DISTINCT oznaka_tabora FROM izvjestaj_tabora)
WHERE oznaka_tabora=incident.tabor_policija) OR tabor_policija=NULL) AND
((SELECT EXISTS(SELECT DISTINCT oznaka_tabora FROM izvjestaj_tabora)
WHERE oznaka_tabora=incident.tabor_vatrogasci) OR tabor_vatrogasci=NULL) AND
((SELECT EXISTS(SELECT DISTINCT oznaka_tabora FROM izvjestaj_tabora)
WHERE oznaka_tabora=incident.tabor_hitna) OR tabor_hitna=NULL);
Does anyone have any idea on how to accomplish this?
Asuming INCIDENT.OZNAKA is the key and you need all 3 to be ralated for the event to open (I am Slovenian that why I understand ;) )
UPDATE incident
SET status='Otvoren'
WHERE oznaka in (
SELECT DISTINCT i.oznaka
FROM incident i
INNER JOIN izvještaj_tabora t1 ON i.tabor_vatrogasci = t1.oznaka_tabora
INNER JOIN izvještaj_tabora t2 ON i.tabor_policija = t2.oznaka_tabora
INNER JOIN izvještaj_tabora t3 ON i.tabor_hitna = t3.oznaka_tabora
WHERE t1.rezultat_izvjestaja='Riješen' AND t2.rezultat_izvjestaja='Riješen' AND t3.rezultat_izvjestaja='Riješen'
)
According to your description the query should look something like this:
UPDATE incident i
SET status = 'Otvoren'
WHERE (tabor_policija IS NULL OR
EXISTS (
SELECT 1 FROM izvjestaj_tabora t
WHERE t.oznaka_tabora = i.tabor_policija
)
)
AND (tabor_vatrogasci IS NULL OR
EXISTS (
SELECT 1 FROM izvjestaj_tabora t
WHERE t.oznaka_tabora = i.tabor_vatrogasci
)
)
AND (tabor_hitna IS NULL OR
EXISTS (
SELECT 1 FROM izvjestaj_tabora t
WHERE t.oznaka_tabora = i.tabor_hitna
)
)
I wonder though, why the connecting table tabor is irrelevant to the operation.
Among other things you fell victim to two widespread misconceptions:
1)
tabor_policija=NULL
This expression aways results in NULL. Since NULL is considered "unknown", if you compare it to anything, the outcome is "unknown" as well. I quote the manual on Comparison Operators:
Do not write expression = NULL because NULL is not "equal to" NULL.
(The null value represents an unknown value, and it is not known
whether two unknown values are equal.)
2)
EXISTS(SELECT DISTINCT oznaka_tabora FROM ...)
In an EXISTS semi-join SELECT items are completely irrelevant. (I use SELECT 1 instead). As the term implies, only existence is checked. The expression returns TRUE or FALSE, SELECT items are ignored. It is particularly pointless to add a DISTINCT clause there.

Using CASE in PostgreSQL to affect multiple columns at once

I have a Postgres SELECT statement with these expressions:
,CASE WHEN (rtp.team_id = rtp.sub_team_id)
THEN 'testing'
ELSE TRIM(rtd2.team_name)
END AS testing_testing
,CASE WHEN (rtp.team_id = rtp.sub_team_id)
THEN 'test example'
ELSE TRIM(rtd2.normal_data)
END AS test_response
,CASE WHEN (rtp.team_id = rtp.sub_team_id)
THEN 'test example #2'
ELSE TRIM(rtd2.normal_data_2)
END AS another_example
In my particular query there are 5 fields whose output depends on whether rtp.team_id = rtp.sub_team_id evaluates true. I'm repeating CASE statements with the same condition over and over.
Is there any way I can combine these CASE expressions to toggle the output of multiple columns in one shot?
1. Standard-SQL: LEFT JOIN a single row of values
You could LEFT JOIN a row of values using the condition (thereby evaluating it once). Then you can add fallback values per column with COALESCE().
This syntax variant is shorter and slightly faster with multiple values - especially interesting for an expensive / lengthy condition:
SELECT COALESCE(x.txt1, trim(r2.team_name)) AS testing_testing
, COALESCE(x.txt2, trim(r2.normal_data)) AS test_response
, COALESCE(x.txt3, trim(r2.normal_data_2)) AS another_example
FROM rtp
JOIN rtd2 r2 ON <unknown condition> -- missing context in question
LEFT JOIN (
SELECT 'testing'::text AS txt1
, 'test example'::text AS txt2
, 'test example #2'::text AS txt3
) x ON rtp.team_id = rtp.sub_team_id;
Since the derived table x consists of a single row, joining without further conditions is fine.
Explicit type casts are necessary in the subquery. I use text in the example (which is the default for string literals anyway). Use your actual data types. The syntax shortcut value::type is Postgres-specific, use cast(value AS type) for standard SQL.
If the condition is not TRUE, all values in x are NULL, and COALESCE kicks in.
Or, since all candidate values come from table rtd2 in your particular case, LEFT JOIN to rtd2 using the original CASE condition and CROSS JOIN to a row with default values:
SELECT COALESCE(trim(r2.team_name), x.txt1) AS testing_testing
, COALESCE(trim(r2.normal_data), x.txt2) AS test_response
, COALESCE(trim(r2.normal_data_2), x.txt3) AS another_example
FROM rtp
LEFT JOIN rtd2 r2 ON <unknown condition> -- missing context in question
AND rtp.team_id = rtp.sub_team_id
CROSS JOIN (
SELECT 'testing'::text AS txt1
, 'test example'::text AS txt2
, 'test example #2'::text AS txt3
) x;
It depends on the join conditions and the rest of the query.
2. PostgreSQL-specific
2a. Expand an array
If your various columns share the same data type, you can use an array in a subquery and expand it in the outer SELECT:
SELECT x.combo[1], x.combo[2], x.combo[3]
FROM (
SELECT CASE WHEN rtp.team_id = rtp.sub_team_id
THEN '{test1,test2,test3}'::text[]
ELSE ARRAY[trim(r2.team_name)
, trim(r2.normal_data)
, trim(r2.normal_data_2)]
END AS combo
FROM rtp
JOIN rtd2 r2 ON <unknown condition>
) x;
It gets more complicated if the columns don't share the same data type. You can either cast them all to text (and optionally convert back in the outer SELECT), or you can ...
2b. Decompose a row type
You can use a custom composite type (row type) to hold values of various types and simply *-expand it in the outer SELECT. Say we have three columns: text, integer and date. For repeated use, create a custom composite type:
CREATE TYPE my_type AS (t1 text, t2 int, t3 date);
Or if the type of an existing table matches, you can just use the table name as composite type.
Or if you only need the type temporarily, you can create a TEMPORARY TABLE, which registers a temporary type for the duration of your session:
CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date);
You could even do this for a single transaction:
CREATE TEMP TABLE my_type (t1 text, t2 int, t3 date) ON COMMIT DROP;
Then you can use this query:
SELECT (x.combo).* -- parenthesis required
FROM (
SELECT CASE WHEN rtp.team_id = rtp.sub_team_id
THEN ('test', 3, now()::date)::my_type -- example values
ELSE (r2.team_name
, r2.int_col
, r2.date_col)::my_type
END AS combo
FROM rtp
JOIN rtd2 r2 ON <unknown condition>
) x;
Or even just (same as above, simpler, shorter, maybe less easy to understand):
SELECT (CASE WHEN rtp.team_id = rtp.sub_team_id
THEN ('test', 3, now()::date)::my_type
ELSE (r2.team_name, r2.int_col, r2.date_col)::my_type
END).*
FROM rtp
JOIN rtd2 r2 ON <unknown condition>;
The CASE expression is evaluated once for every column this way. If the evaluation is not trivial, the other variant with a subquery will be faster.
Not sure that it would be an improvement, but you could union the SELECT one way with itself the other way:
SELECT
...,
'testing' AS testing_testing,
'test example' AS test_response,
'test example #2' AS another_example, ...
FROM ...
WHERE rtp.team_id = rtp.sub_team_id AND ...
UNION
SELECT
...,
TRIM(rtd2.team_name) AS testing_testing,
TRIM(rtd2.normal_data) AS test_response,
TRIM(rtd2.normal_data_2) AS another_example, ...
WHERE rtp.team_id <> rtp.sub_team_id AND ...;
The column names can safely be omitted from the second query, assuming you bring them out in the same order as in the first.
You may want to make each of those a separate query using common table expressions (CTEs). If you're worried about this changing the order, you can make it a subquery and apply an ORDER BY around it.

Writing a single UPDATE statement that prevents duplicates

I've been trying for a few hours (probably more than I needed to) to figure out the best way to write an update sql query that will dissallow duplicates on the column I am updating.
Meaning, if TableA.ColA already has a name 'TEST1', then when I'm changing another record, then I simply can't pick a value for ColA to be 'TEST1'.
It's pretty easy to simply just separate the query into a select, and use a server layer code that would allow conditional logic:
SELECT ID, NAME FROM TABLEA WHERE NAME = 'TEST1'
IF TableA.recordcount > 0 then
UPDATE SET NAME = 'TEST1' WHERE ID = 1234
END IF
But I'm more interested to see if these two queries can be combined into a single query.
I am using Oracle to figure things out, but I'd love to see a SQL Server query as well. I figured a MERGE statement can work, but for obvious reasons you can't have the clause:
..etc.. WHEN NOT MATCHED UPDATE SET ..etc.. WHERE ID = 1234
AND you can't update a column if it's mentioned in the join (oracle limitation but not limited to SQL Server)
ALSO, I know you can put a constraint on a column that prevents duplicate values, but I'd be interested to see if there is such a query that can do this without using constraint.
Here is an example start-up attempt on my end just to see what I can come up with (explanations on it failed is not necessary):
ERROR: ORA-01732: data manipulation operation not legal on this view
UPDATE (
SELECT d.NAME, ch.NAME FROM (
SELECT 'test1' AS NAME, '2722' AS ID
FROM DUAL
) d
LEFT JOIN TABLEA a
ON UPPER(a.name) = UPPER(d.name)
)
SET a.name = 'test2'
WHERE a.name is null and a.id = d.id
I have tried merge, but just gave up thinking it's not possible. I've also considered not exists (but I'd have to be careful since I might accidentally update every other record that doesn't match a criteria)
It should be straightforward:
update personnel
set personnel_number = 'xyz'
where person_id = 1001
and not exists (select * from personnel where personnel_number = 'xyz');
If I understand correctly, you want to conditionally update a field, assuming the value is not found. The following query does this. It should work in both SQL Server and Oracle:
update table1
set name = 'Test1'
where (select count(*) from table1 where name = 'Test1') > 0 and
id = 1234