I have a SQL query built that returns a singular column of figures. Sample is shown below. I need to enhance this in a singular query and retrieve a 2nd set of figures using similar filters/parameters (instead of status=E I'd look for category=E). This query has gotten fairly complex for my knowledge though and I'm a bit stumped on how to approach adding this additional SELECT statement to get a 2nd column. Appreciate if anyone can point me in the right direction.
SELECT Count(eqnbr) EQUIP,
imp_exp,
'TITLE' TITLE
FROM (SELECT cy.container EQNbr,
cy.location_position "POS",
Substr(cy.location_position, 1, 1) Row_Nbr,
CASE
WHEN Substr(cy.location_position, 1, 3) IN (
'M01', 'N03', 'N04', 'N05',
'N06', 'N07', 'N08', 'N09' ) THEN
'Rail'
WHEN Substr(cy.location_position, 1, 1) IN ( 'F', 'G', 'H', 'J',
'K', 'L', 'M', 'P',
'R', 'S' ) THEN
'Locals'
WHEN Substr(cy.location_position, 1, 1) IN ( 'B', 'D' ) THEN
'Export'
ELSE Concat ('Row ', Substr(cy.location_position, 1, 1))
END IMP_EXP
FROM current_yard cy
WHERE eq_class = 'CTR'
AND location_position NOT LIKE 'CT%'
AND using_line NOT IN ( 'TEST', 'UNK', 'TST', 'B125',
'BO77', 'BR75' )
AND using_line IS NOT NULL
AND ( container NOT LIKE 'TEST%'
OR container NOT LIKE 'KENT%' )
AND Length(container) >= 10
AND status = 'E'
AND Substr(cy.location_position, 1, 1) NOT IN
( '1', '2', '3', '4',
'5', '6', '7', '8',
'9', '0', 'A', 'C',
'E', 'U', 'V', 'W', 'X' )) a
GROUP BY imp_exp
ORDER BY 2 ASC
Related
I am trying to create a encryption alghoritm in ruby. The encryption works fine, but the decryption part fails. The error is at line 67, and says the following:
decryption.rb:67:ln '/': divided by zero (ZeroDivisionError)
I have no idea why this is happening and i cannot find a answer to my question online.
This is the source code:
print ">"
ciphertext = gets.chomp
print ">"
symetricKey = gets.chomp
symetricKey.gsub! 'a', '1'
symetricKey.gsub! 'b', '2'
symetricKey.gsub! 'c', '3'
symetricKey.gsub! 'd', '4'
symetricKey.gsub! 'e', '5'
symetricKey.gsub! 'f', '6'
symetricKey.gsub! 'g', '7'
symetricKey.gsub! 'h', '8'
symetricKey.gsub! 'i', '9'
symetricKey.gsub! 'j', '10'
symetricKey.gsub! 'k', '11'
symetricKey.gsub! 'l', '12'
symetricKey.gsub! 'm', '13'
symetricKey.gsub! 'n', '14'
symetricKey.gsub! 'o', '15'
symetricKey.gsub! 'p', '16'
symetricKey.gsub! 'q', '17'
symetricKey.gsub! 'r', '18'
symetricKey.gsub! 's', '19'
symetricKey.gsub! 't', '20'
symetricKey.gsub! 'u', '21'
symetricKey.gsub! 'v', '22'
symetricKey.gsub! 'w', '23'
symetricKey.gsub! 'x', '24'
symetricKey.gsub! 'y', '25'
symetricKey.gsub! 'z', '26'
symetricKey=symetricKey.to_i
ciphertext.gsub! 'a', '1'
ciphertext.gsub! 'b', '2'
ciphertext.gsub! 'c', '3'
ciphertext.gsub! 'd', '4'
ciphertext.gsub! 'e', '5'
ciphertext.gsub! 'f', '6'
ciphertext.gsub! 'g', '7'
ciphertext.gsub! 'h', '8'
ciphertext.gsub! 'i', '9'
ciphertext.gsub! 'j', '10'
ciphertext.gsub! 'k', '11'
ciphertext.gsub! 'l', '12'
ciphertext.gsub! 'm', '13'
ciphertext.gsub! 'n', '14'
ciphertext.gsub! 'o', '15'
ciphertext.gsub! 'p', '16'
ciphertext.gsub! 'q', '17'
ciphertext.gsub! 'r', '18'
ciphertext.gsub! 's', '19'
ciphertext.gsub! 't', '20'
ciphertext.gsub! 'u', '21'
ciphertext.gsub! 'v', '22'
ciphertext.gsub! 'w', '23'
ciphertext.gsub! 'x', '24'
ciphertext.gsub! 'y', '25'
ciphertext.gsub! 'z', '26'
ciphertext = ciphertext.to_i
cleartext = ciphertext / (symetricKey / symetricKey / 100)
print"\n"
cleartext.to_s
cleartext.gsub! '1' ,'a'
cleartext.gsub! '2' ,'b'
cleartext.gsub! '3' ,'c'
cleartext.gsub! '4' ,'d'
cleartext.gsub! '5' ,'e'
cleartext.gsub! '6' ,'f'
cleartext.gsub! '7' ,'g'
cleartext.gsub! '8' ,'h'
cleartext.gsub! '9' ,'i'
cleartext.gsub! '10' ,'j'
cleartext.gsub! '11' ,'k'
cleartext.gsub! '12' ,'l'
cleartext.gsub! '13' ,'m'
cleartext.gsub! '14' ,'n'
cleartext.gsub! '15' ,'o'
cleartext.gsub! '16' ,'p'
cleartext.gsub! '17' ,'q'
cleartext.gsub! '18' ,'r'
cleartext.gsub! '19' ,'s'
cleartext.gsub! '20' ,'t'
cleartext.gsub! '21' ,'u'
cleartext.gsub! '22' ,'v'
cleartext.gsub! '23' ,'w'
cleartext.gsub! '24' ,'x'
cleartext.gsub! '25' ,'y'
cleartext.gsub! '26' ,'z'
puts cleartext
It doesn't work because the formula ciphertext / (symetricKey / symetricKey / 100) makes no sense at all.
symetricKey / symetricKey is always 1, divided by 100 that's always 0.01
symetricKey / symetricKey / 100 both operands are integers, so 0.01 is rounded down to 0
ciphertext / (symetricKey / symetricKey / 100) is equivalent to ciphertext / 0 (see 2.)
Your error is exactly what it says in the message: you're dividing by 0.
EDIT: As a small bonus, your code is broken anyway. 'k' for example is converted into 11, but when decrypting that will turn into 'aa'
Your question has been answered, but I'd like to suggest a more Ruby-like way to solve your problem.
If you look at the doc for Hash#gsub you will see that the second form of the method, written str.gsub(pattern, hash), where pattern is generally a regular expression and hash is, of course, a hash. Here's an example.
h = { 'c'=>'C', 'a'=>'A', 'n'=>'N', 'd'=>'D', 'o'=>'$', 'g'=>'G' }
'cat and dog.'.gsub(/./, h)
#=> "CAANDD$G"
/./ is a regular expression that simply matches any one character in str. It first matches 'c', then 'a', and so on. Consider the first letter, 'c'. Ruby checks to see if the hash h has a key 'c'. It does, so that character is replaced with the value of 'c' in the hash, 'C'. Next, 'a' is replaced with 'A'. h does not have a key 't', however, so Ruby converts 't' to an empty string. Similarly, the characters ' ' (a space) and '.' (a period) are not keys in h, so those characters are also converted to empty strings.
This form of gsub seems perfect for encrypting and decrypting strings.
Let's first construct the encoding hash.
arr = ('a'..'z').zip('01'..'26')
#=> [["a", "01"], ["b", "02"],..., ["z", "26"]]
encode = arr.to_h
#=> {"a"=>"01", "b"=>"02",..., "z"=>"26"}
encode[' '] = "27"
encode['.'] = "28"
So now
encode
#=> {"a"=>"01", "b"=>"02",..., "z"=>"26", " "=>"27", "."=>"." }
'a'..'z' and '01'..'2' are Ranges. See the docs for Enumerable#zip and Array#to_h. We would normally write those two lines as a single chained expression.
encode = ('a'..'z').zip('01'..'26').to_h
Notice that the values begin with "01", so that all are strings of the same length (2). If we started the values with "1" how could we decode the string "1226"? Would that be 'abbd' (1-2-3-4), 'abz' (1-2-26), 'lz' (12-26) or one of the other possibilities. That is not an issue if all the values of the hash encode are strings of length 2.
We could construct the hash for decoding in the same way( {'01'=>'a', '02'=>'b',...}), but it's easier to use the method Hash#invert:
decode = encode.invert
#=> {"01"=>"a", "02"=>"b",..., "26"=>"z", "27"=>" ", "28"=>"."}
If the string to be encrypted is
str = "how now, brown cow."
we can encode it with
encrypted = str.gsub(/./, encode)
#=> "081523271415232702181523142703152328"
which can then be decoded with
decoded = encrypted.gsub(/../, decode)
#=> "how now, brown cow."
Notice that the regular expression ("regex") for decoding matches any two characters at a time.
Two points. Firstly, we could use Hash#update (aka merge!) to write
encode = ('a'..'z').zip('01'..'26').to_h
encode.update( ' '=>"27", '.'=>"28" )
Ruby allows us to write encode.update({ ' '=>"27", '.'=>"28" }) without the braces (an example of syntactic sugar).
The better way is to use Hash#default_proc= to write
encode = ('a'..'z').zip('01'..'26').to_h
encode.default_proc = proc { |h,k| h[k] = k }
This is a bit complicated for a Ruby newbie, but the effect is to cause encode[k] to return k if encode does not have a key k. For example, encode['.'] #=> '.'.
I have a query that is working on oracle 12c but not in 10g. I am not sure what the problem is:
My query is:
WITH tab1(rn,begin_chq_num,chq_lvs_stat,chq_num_of_lvs,tes) AS
(SELECT 1 rn,
begin_chq_num,
chq_lvs_stat,
chq_num_of_lvs,
SUBSTR(chq_lvs_stat,1,1) tes
FROM tbaadm.chq_book_table
WHERE del_flg != 'Y'
AND acid IN
(SELECT acid
FROM tbaadm.GENERAL_ACCT_MAST_TABLE
WHERE foracid = '01411110171546'
)
UNION ALL
SELECT rn + 1 rn,
begin_chq_num,
chq_lvs_stat,
chq_num_of_lvs,
SUBSTR(chq_lvs_stat,rn + 1,1) tes
FROM tab1
WHERE rn < chq_num_of_lvs
)
SELECT
CASE
WHEN begin_chq_num = 1
THEN rn
ELSE begin_chq_num +(rn-1)
END cheque_num,
begin_chq_num
||'-'
||(chq_num_of_lvs+begin_chq_num-1) cheque_range,
DECODE(tes, 'I', 'Issued', 'P', 'Cleared', 'U', 'Unused', 'S', 'Stopped', 'C', 'Cautioned', 'D', 'Destroyed', 'R', 'Returned Paid', 'T', 'Transfered') status
FROM tab1
ORDER BY chq_lvs_stat,
rn;
The error is :
ORA-32033: unsupported column aliasing
32033. 00000 - "unsupported column aliasing"
*Cause: column aliasing in WITH clause is not supported yet
*Action: specify aliasing in defintion subquery and retry
What should I do different?
In Oracle 10g, the sub-query factoring clause does not support column aliases or recursive sub-queries. The syntax you are using appears in 11gR2.
You need to change:
WITH tab1(rn,begin_chq_num,chq_lvs_stat,chq_num_of_lvs,tes) AS
To:
WITH tab1 AS
And find a different solution that does not use a recursive subquery factoring clause.
I think you could do this in Oracle 10g:
WITH tab1 AS (
SELECT l.COLUMN_VALUE rn,
begin_chq_num,
chq_lvs_stat,
chq_num_of_lvs,
SUBSTR(chq_lvs_stat,l.COLUMN_VALUE,1) tes
FROM tbaadm.chq_book_table t,
TABLE(
CAST(
MULTISET(
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= LENGTH( t.chq_lvs_stat )
)
AS SYS.ODCINUMBERLIST
)
) l
WHERE del_flg != 'Y'
AND acid IN ( SELECT acid
FROM tbaadm.GENERAL_ACCT_MAST_TABLE
WHERE foracid = '01411110171546'
)
)
SELECT CASE
WHEN begin_chq_num = 1
THEN rn
ELSE begin_chq_num +(rn-1)
END cheque_num,
begin_chq_num
||'-'
||(chq_num_of_lvs+begin_chq_num-1) cheque_range,
DECODE(
tes,
'I', 'Issued',
'P', 'Cleared',
'U', 'Unused',
'S', 'Stopped',
'C', 'Cautioned',
'D', 'Destroyed',
'R', 'Returned Paid',
'T', 'Transfered'
) status
FROM tab1
ORDER BY chq_lvs_stat, rn;
I am working on a database system that uses SQL syntax. However I am unable to use the cross apply in the code below. Is there a way to rewrite this without applies?
declare #rsBuildDetails table(dt datetime, build varchar(255), val varchar(255));
insert into #rsBuildDetails (dt, build, val)
values ('20100101', '1', 'pass')
,('20100102', '2', 'fail')
,('20100103', '3', 'pass')
,('20100104', '4', 'fail')
,('20100105', '5', 'fail')
,('20100106', '6', 'fail')
,('20100107', '7', 'pass')
,('20100108', '8', 'pass')
,('20100109', '9', 'pass')
,('20100110', '10', 'fail');
with passed as
(
select *
from #rsBuildDetails
where val='pass'
)
select distinct
preFail.dt AS FailedDt,
postFail.dt AS SecondFailedDt
from
passed
cross apply
(select top 1
pre.*
from
#rsBuildDetails as pre
where
pre.dt < passed.dt
and pre.val = 'fail'
order by
pre.dt desc) as preFail
cross apply
(select top 1
post.*
from
#rsBuildDetails as post
where
post.dt > passed.dt
and post.val = 'fail'
order by
post.dt asc) as postFail
You might try to transfer the CTE and all applies to inlined sub-selects:
declare #rsBuildDetails table(dt datetime, build varchar(255), val varchar(255));
insert into #rsBuildDetails (dt, build, val) values
('20100101', '1', 'pass')
,('20100102', '2', 'fail')
,('20100103', '3', 'pass')
,('20100104', '4', 'fail')
,('20100105', '5', 'fail')
,('20100106', '6', 'fail')
,('20100107', '7', 'pass')
,('20100108', '8', 'pass')
,('20100109', '9', 'pass')
,('20100110', '10', 'fail');
select *
from
(
select distinct
(
select top 1 pre.Dt
from #rsBuildDetails as pre
where pre.dt<passed.dt
and pre.val='fail'
order by pre.dt desc
) as FailedDt
,(
select top 1 post.Dt
from #rsBuildDetails as post
where post.dt>passed.dt
and post.val='fail'
order by post.dt asc
) AS SecondFailedDt
from
(
select *
from #rsBuildDetails
where val='pass'
) AS passed
) AS tbl
where tbl.FailedDt IS NOT NULL
AND tbl.SecondFailedDt IS NOT NULL
I've a column that have a varchar2 like this: ..x...y...z..
I want to replace x to 1, y to 2 and z to 3.
Is it possible to have multiple replace after each other in select statement to replace these characters?
(select)
replace(varchar2, 'x', '1')
replace(varchar2, 'y', '2')
replace(varchar2, 'z', '3')
Or use TRANSLATE function if that fits your needs http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions216.htm#SQLRF06145
Do you mean something like this:
replace(replace(replace(varchar2, 'x', '1'), 'y', '2'), 'z', '3')
How can I get the last letter of a string and check if it's vowel or consonant? I am using oracle 10g.
Here is what I came up with already:
SELECT last_name,
Substr(last_name, -1, 1) "Last letter",
Substr(last_name, 1, 1) "First letter",
CASE
WHEN Substr(last_name, -1, 1) IN ( 'a', 'e', 'i', 'o', 'u' ) THEN
'ends with a vowel'
WHEN Substr(last_name, -1, 1) IN ( 'b', 'c', 'd', 'f',
'g', 'h', 'j', 'k',
'l', 'm', 'n', 'p',
'q', 'r', 's', 't',
'v', 'w', 'x', 'y', 'z' ) THEN
'ends with a consonant'
END "Last Letter Description",
CASE
WHEN Substr(last_name, 1, 1) IN ( 'a', 'e', 'i', 'o', 'u' ) THEN
'starts with a consonant'
WHEN Substr(last_name, 1, 1) IN ( 'b', 'c', 'd', 'f',
'g', 'h', 'j', 'k',
'l', 'm', 'n', 'p',
'q', 'r', 's', 't',
'v', 'w', 'x', 'y', 'z' ) THEN
'starts with a consonant'
END "First Letter Description"
FROM employees
GROUP BY first_name,
last_name
Now when you execute this on oracle 10g the "First Letter Description" is empty! What is wrong with my code?
Try this, not complete, but with easy adjustments you can make it work the way you want:
FUNCTION last_is_vowel (string_in VARCHAR2)
RETURN BOOLEAN
IS
BEGIN
RETURN CASE WHEN LOWER(SUBSTR(string_in, -1)) IN ('a', 'e', 'i', 'o', 'u')
THEN TRUE
ELSE FALSE
END;
END last_is_vowel;
Look at your data. Chances are the first character in employees.last_name is capitalized. Remember, Oracle is case sensitive. You can user UPPER() or LOWER() to help find your match.
Also it'd be more efficient to search just for vowels and use an else statement for to find exclusions as João suggests.
SELECT last_name,
Substr(last_name, -1, 1) "Last character",
Substr(last_name, 1, 1) "First character",
CASE
WHEN lower(Substr(last_name, -1, 1)) IN ( 'a', 'e', 'i', 'o', 'u' ) THEN
'ends with a vowel'
ELSE
'does not end with a vowel'
END "Last Letter Description",
CASE
WHEN lower(Substr(last_name, 1, 1)) IN ( 'a', 'e', 'i', 'o', 'u' ) THEN
'starts with a vowel'
ELSE
'does not start with a vowel'
END "First Letter Description"
FROM employees
GROUP BY first_name,
last_name