In my query I want to add the and clause in query if a specific condition occur.
See the where clause of my query
1 and ps.dept=dept.deptid
2 and ps.sdept=deptsub.deptid
3 and
4 if(ps.dept<>ps.sdept)
5 begin
6 deptsub.Parent=dept.deptid
7 end
8 and ps.deptcategory=deptcat.category
At 4 I want if condition fulfil then 6 should be added in query else not how is this possible.thanks!
How about:
and ps.dept=dept.deptid
and ps.sdept=deptsub.deptid
and ( ps.dept=ps.sdept or deptsub.Parent=dept.deptid )
and ps.deptcategory=deptcat.category
Try replacing lines 4, 5, 6, and 7 with this:
deptsub.Parent =
case when ps.dept <> ps.sdept then dept.deptid
else deptsub.Parent
end
The case statement will substitute dept.deptid when your condition is met, otherwise it will just substitute deptsub.parent - which will always = deptsub.parent
and ps.dept=dept.deptid
and ps.sdept=deptsub.deptid
and
(
((ps.dept<>ps.sdept) and (deptsub.Parent=dept.deptid))
or
(ps.dept = ps.sdept)
)
and ps.deptcategory=deptcat.category
Related
Have a table where one of the columns has all of the info I need for a report.
I want to substring certain portions of this column as a column in this report, but the problem is that this column has results from 3 varying character lengths.
Example:
Row1: 20180101_ABC_12
Row2: 20180102_DEFG_23
Row3: 20180103_HIJKL_45
In this particular example I want the middle portion (eg. ABC) to be a column called 'Initials', problem is I am using CASE logic for each LEN. Not sure else how to achieve this.
My sample query below. It pulls all of the possible options, but as separate columns. What would I need to do to have these 3 options pull into one column, let's call it 'Initials'?
Thanks
SELECT
FileName
, CASE WHEN LEN(FileName) = 10 THEN SUBSTRING(FileName, 10, 3) ELSE NULL END
, CASE WHEN LEN(FileName) = 11 THEN SUBSTRING(FileName, 10, 4) ELSE NULL END
, CASE WHEN LEN(FileName) = 12 THEN SUBSTRING(FileName, 10, 5) ELSE NULL END
FROM File
In Tableau, you would accomplish this using a calculated field.
Initials:
CASE LEN(FileName)
WHEN 10 THEN SUBSTRING(FileName, 10, 3)
WHEN 11 THEN SUBSTRING(FileName, 10, 4)
WHEN 12 THEN SUBSTRING(FileName, 10, 5)
END
Or maybe
SUBSTRING(FileName
,10
,CASE LEN(FileName)
WHEN 10 THEN 3
WHEN 11 THEN 4
WHEN 12 THEN 5
END
)
But barring the more technical aspect, this can be solved with math (assuming your data is either limited to the 10, 11, and 12, or that the pattern holds):
SUBSTRING(FileName
,10
,LEN(FileName)-7
)
You need 1 CASE statement covering every possible case and not 3 separate ones, because each one creates a new column:
SELECT
FileName
, CASE LEN(FileName)
WHEN 10 THEN SUBSTRING(FileName, 10, 3)
WHEN 11 THEN SUBSTRING(FileName, 10, 4)
WHEN 12 THEN SUBSTRING(FileName, 10, 5)
ELSE NULL
END AS Initials
FROM File
Another way to get everything between the 2 _:
SELECT
FileName
, substring(
left(FileName, len(FileName) - charindex('_', reverse(FileName) + '_')),
charindex('_', FileName) + 1,
len(FileName)
) AS Initials
FROM File
but from your logic I assume that the values in column FileName have the same patern:
<9 digits>_<Initials>_<2 digits>
If this is the case then you can get what you want like this:
SELECT
FileName
, substring(FileName, 10, len(FileName) - 12) AS Initials
FROM File
I have been having fun with an issue where I need to break apart a string in SQL Server 2012 and test for values it may or may not contain. The values, when present, will be separated by up to two different ; symbols.
When there is nothing, it will be blank.
When there is a single value, it will show up without the delimiter.
When there are two or more, up to 3, they will be separated by the delimiter.
As I said, if there is nothing in the record, it will be blank. Below are some example of how the data may come across:
' ',
'1',
'24',
'15;1;24',
'10;1;22',
'5;1;7',
'12;1',
'10;12',
'1;5',
'1;1;1',
'15;20;22'
I have searched the forums and found many clues, but I have not been able to come up with a total solution given all potential data values. Essentially, I would like to break it into 3 separate values.
text before the first delimiter or in the absence of the delimiter, just the text.
Text after the first delimiter and before the second in situation where there are two delimiters.
The following has worked consistently:
substring(SUBSTRING(Food_Desc, charindex(';', Food_Desc) + 1, 4), 0,
charindex(';', SUBSTRING(Food_Desc, charindex(';', Food_Desc) + 1, 4))) as [Middle]
Text after the second delimiter in the even there are two delimiters and there is a third value
The main challenge is the fact that the delimiter, when present, moves depending on the value in the table. values 1-9 make it show up as the second character in the string, values 10-24 make it show up as the 3rd, etc.
Any help would be greatly appreciated.
This is simple if you have a well written t-sql splitter function. For this solution I'm using Jeff Moden's delimitedsplit8k.
sample data and solution
DECLARE #table table (someid int identity, sometext varchar(100));
INSERT #table VALUES (' '),('1'),('24'),('15;1;24'),('10;1;22'),
('5;1;7'),('12;1'),('10;12'),('1;5'),('1;1;1'),('15;20;22');
SELECT
someid,
sometext,
ItemNumber,
Item
FROM #table
CROSS APPLY dbo.DelimitedSplit8K_LEAD(sometext, ';');
results
someid sometext ItemNumber Item
----------- ----------------- ----------- --------
1 1
2 1 1 1
3 24 1 24
4 15;1;24 1 15
4 15;1;24 2 1
4 15;1;24 3 24
5 10;1;22 1 10
5 10;1;22 2 1
5 10;1;22 3 22
6 5;1;7 1 5
6 5;1;7 2 1
6 5;1;7 3 7
7 12;1 1 12
7 12;1 2 1
8 10;12 1 10
8 10;12 2 12
9 1;5 1 1
9 1;5 2 5
10 1;1;1 1 1
10 1;1;1 2 1
10 1;1;1 3 1
11 15;20;22 1 15
11 15;20;22 2 20
11 15;20;22 3 22
Below is a modified version of a similar question How do I split a string so I can access item x?. Changing the text value for #sample to each of your possibilities listed seemed to work for me.
DECLARE #sample VARCHAR(200) = '15;20;22';
DECLARE #individual VARCHAR(20) = NULL;
WHILE LEN(#sample) > 0
BEGIN
IF PATINDEX('%;%', #sample) > 0
BEGIN
SET #individual = SUBSTRING(#sample, 0, PATINDEX('%;%', #sample));
SELECT #individual;
SET #sample = SUBSTRING(#sample, LEN(#individual + ';') + 1, LEN(#sample));
END;
ELSE
BEGIN
SET #individual = #sample;
SET #sample = NULL;
SELECT #individual;
END;
END;
I am having a table in following structure.
_________________________________
|| ExpObjkey Exp1 Exp2 operator||
________________________________
1 2 3 +
2 4 5 +
3 6 7 -
I want to have records in the following order:
for expObjKey=1, we will have
ExpObjKey Expression
1 (4+5)+(6-7)
explanation:
for ExpObjKey 1 we will have 2 +3
then 2 will have 4+5
and 3 will have 6+7.
Its more like a hierarchy.
I have tried lots of possible ways but no near the solution.
SELECT expObjkey, SYS_CONNECT_BY_PATH(exp1||' ' ||operator|| exp2||')', ' ( ') "Path"
FROM bpmn_expression
CONNECT BY PRIOR
exp1=expObjkey or exp2=expObjkey
start with expObjkey=1
I don't think you can do this with a hierarchical query, but I'd be interested to be proven wrong. You'd need to start at the bottom of the tree and work your way up to allow the substitutions to happen; but then there doesn't seem to be a way to combine the partial expressions that produces. It might be possible with recursive subquery factoring, but that isn't available until 11gR2.
On 10g you could use your own recursive function to generate what you need:
create or replace function get_expression(p_key bpmn_expression.expobjkey%type)
return varchar2 is
row bpmn_expression%rowtype;
begin
select * into row from bpmn_expression where expobjkey = p_key;
return '(' || get_expression(row.exp1)
|| row.operator || get_expression(row.exp2) || ')';
exception
when no_data_found then
return to_char(p_key);
end;
/
select get_expression(1) as expression from dual;
EXPRESSION
------------------------------
((4+5)+(6-7))
SQL Fiddle.
You can strip the outer parentheses with trim or regexp_replace if you want to, but they may be acceptable.
If you add another layer, say a record with values 7, 8, 9, '*', this would give:
EXPRESSION
------------------------------
((4+5)+(6-(8*9)))
SQL Fiddle.
But this isn't going to be very efficient against a large data set, since it will do a lot of single-row look-ups.
When I try to run the following statement, I get this error:
"A SELECT statement that assigns a value to a variable must not be combined with data-retrieval operations."
DECLARE #OFR DECIMAL(18,2)
;
SELECT #OFR =
CASE SUM(ofr.Quantity)
WHEN 0 THEN 0
ELSE SUM(ofr.Gross) / SUM(ofr.Quantity)
END
FROM DistributionCosts ofr
;
SELECT #OFR
I just want to stick the result of that case statement into a variable and I'm getting stuck here.
Any ideas?
Thanks.
Are you sure this is where your error is? I just ran the statement below and it worked:
DECLARE #OFR DECIMAL(18,2)
;
with DistributionCosts as
(
select 1 as quantity, 5 as gross
union
select 5 , 20
)
SELECT #OFR =
CASE SUM(ofr.Quantity)
WHEN 0 THEN 0
ELSE SUM(ofr.Gross) / SUM(ofr.Quantity)
END
FROM DistributionCosts ofr
;
SELECT #OFR
If I select a column in addition to setting a variable I do get your error... If you are selecting another column you will need to either stop selecting that column or assign that column to a local variable as well.
Can anyone tell me how to translate the following T-SQL statement:
SELECT fileld1 = CASE
WHEN T.option1 THEN -1
ELSE
CASE WHEN T.option2 THEN 0
ELSE 1
END
END
FROM Table1 AS T
The point is I need to validate two different options from the table for a single field in the select statement..
I have tried to do somthing with an IF statement in pl/sql, but it just doesnt work for me:
SELECT IF T.option1 THEN -1
ELSE IF T.option2 THEN 0
ELSE 1
END
FROM Table1 AS T
I am not actually sure how to write IF statement inside the SELECT statement..
And also, I need to do it INSIDE the select statement because I am constructing a view.
Use:
SELECT CASE
WHEN T.option1 = ? THEN -1
WHEN T.option2 = ? THEN 0
ELSE 1
END AS field1
FROM Table1 AS T
I can't get your original TSQL to work - I get:
Msg 4145, Level 15, State 1, Line 4
An expression of non-boolean type specified in a context where a condition is expected, near 'THEN'.
...because there's no value evaluation. If you're checking if the columns are null, you'll need to use:
SELECT CASE
WHEN T.option1 IS NULL THEN -1
WHEN T.option2 IS NULL THEN 0
ELSE 1
END AS field1
FROM Table1 AS T
...or if you need when they are not null:
SELECT CASE
WHEN T.option1 IS NOT NULL THEN -1
WHEN T.option2 IS NOT NULL THEN 0
ELSE 1
END AS field1
FROM Table1 AS T
CASE expressions shortcircuit - if the first WHEN matches, it returns the value & exits handling for that row - so the options afterwards aren't considered.
If I remember correctly, PL/SQL also supports the case. You just would have to move the column alias from "field1=" before the expression to "AS filed1" after the expression.