Is there a better way to parse value into multiple columns? - tsql

I have a value that needs to be parsed into a potential three values:
MasterUnit
Unit1
Unit2
Unit3
10ABC
10A
10B
10C
10AB
10A
10B
NULL
I'm accomplishing what I need in the below script. My question to you... Is there a better, more efficient way to do so (in fewer lines of code)?
cast([UnitNum] as char(5)) as MasterUnit,
left(cast([UnitNum] as char(5)), 3) as Unit1,
case
when (left(left(cast([UnitNum] as char(5)), 2) + right(cast([UnitNum] as char(5)), 2),3)) = left(cast([UnitNum] as char(5)), 2)
then NULL
else (left(left(cast([UnitNum] as char(5)), 2) + right(cast([UnitNum] as char(5)), 2),3))
end as Unit2,
case
when (left(cast([UnitNum] as char(5)), 2)) + (right(cast([UnitNum] as char(5)), 1)) = left([UnitNum],2)
then NULL
else (left(cast([UnitNum] as char(5)), 2) + right(cast([UnitNum] as char(5)), 1))
end as Unit3

With a little bit of string manipulation and a CROSS APPLY
Select A.*
,Unit1 = S1+nullif(substring(S2,1,1),'')
,Unit2 = S1+nullif(substring(S2,2,1),'')
,Unit3 = S1+nullif(substring(S2,3,1),'')
From YourTable A
Cross Apply ( values ( left(MasterUnit,patindex('%[^0-9]%',MasterUnit)-1),substring(MasterUnit,patindex('%[^0-9]%',MasterUnit),100) ) ) B(S1,S2)
Reults

Making some assumptions about your sample data, perhaps something like the following using a cross apply to re-use the initial two characters is about as minimal as possible :
select MasterUnit,
u + NullIf(Substring(MasterUnit,3,1),'') Unit1,
u + NullIf(substring(MasterUnit,4,1),'') Unit2,
u + NullIf(substring(MasterUnit,5,1),'') Unit3
from t
cross apply(values(Left(MasterUnit,2)))m(u);

Related

IIF Condition Ques

Can someone explain this condition, because I'm getting wrong Time data eg : I'm expecting sch departure time as 15.10 but I'm getting 15.01
[Sch Dep Time] = IIF(DATEPART(Hour,[Journey and Details.schdeptime]) < 10 AND DATEPART(Minute,[Journey and Details.schdeptime]) < 10,
('0' + DATEPART(Hour,[Journey and Details.schdeptime]) + ':0' + DATEPART(Minute,[Journey and Details.schdeptime])),
IIF(DATEPART(Hour,[Journey and Details.schdeptime]) < 10,
('0' + DATEPART(Hour,[Journey and Details.schdeptime]) + ':' + DATEPART(Minute,[Journey and Details.schdeptime])),
(DATEPART(Hour,[Journey and Details.schdeptime]) + ':0' + DATEPART(Minute,[Journey and Details.schdeptime]))))
Update
It suddenly hit me that [Sch Dep Time] should contain the time component of the dataTime value stored in [Journey and Details.schdeptime], in a minute resolution. For that, you don't need to mess around with specific date parts and string concatenation, all you have to do is use convert:
[Sch Dep Time] = CONVERT(char(5), [Journey and Details.schdeptime], 108)
The 108 style returns hh:mm:ss (24 hours), and by using char(5) you are just taking the first 5 chars of that string - hh:mm.
First version
You have overcomplicated things. Try using the old right('00' + val, 2) trick instead:
[Sch Dep Time] = RIGHT('00' + CAST(DATEPART(Hour,[Journey and Details.schdeptime]) AS VARCHAR(2)), 2) + ':' +
RIGHT('00' + CAST(DATEPART(Minute,[Journey and Details.schdeptime]) AS VARCHAR(2)), 2)
Exlpanation:
You start off by concatenating leading zeroes to the string you want.
Suppose you have a string representing a number that must always have 4 digits, but it might be 1234 or 0003 - so you start by doing '0000' + #YourNumber.
Then, you use RIGHT to trim off any unwanted zeros - suppose you now have 000023, but you want 0023 - you do RIGHT('000023', 4) to get the last 4 chars.

Does anybody know how to find the dual of the following (Boolean Algebra)? p*(q+r')

Does anybody know how to find the dual of the following (Boolean Algebra)?
p*(q+r')
Where * stands for AND, + stands for OR, and ' stands for NOT.
I have the following, but it is incorrect:
p + (qr')
not a and not b => not (a or b)
Here a = p', b = (q+r')' = (q'r). Hence p*(q+r') = (p'+q'r)'

GROUP BY Function in Progress OpenEdge

I am trying to find out how to do the Progress equivalent of a "GROUP BY" function. I am trying to write a procedure that will list product inventory information for multiple locations. Right now, it is listing the product information twice; once for each location. I have tried the BREAK BY functional unsuccessfully. My current & desired output and code is below:
Current Output:
Desired Output:
DEF INPUT PARAMETER ip-um AS CHARACTER NO-UNDO.
MESSAGE
"ProdCode" + "^" +
"ProdName" + "^" +
"ProdUM" + "^" +
"GrossPkgdWeight" + "^" +
"QtyOH - LOC1" + "^" +
"QtyOH - LOC2"
SKIP.
FOR EACH product-um WHERE
product-um.gross-pkgd-weight <= 0.0000
NO-LOCK,
EACH product WHERE
product.product-key = product-um.product-key AND
product.can-be-sold = YES
NO-LOCK,
EACH inventory WHERE
inventory.product-key = product.product-key AND
inventory.qoh > 0 AND
inventory.level = 2
NO-LOCK,
EACH um WHERE
um.um-key = product-um.um-key AND
um.um = ip-um
NO-LOCK
BREAK BY product.product-code:
MESSAGE
product.product-code + "^" +
product.product-name + "^" +
um.um-code + "^" +
STRING(product-um.gross-pkgd-weight) + "^" +
IF inventory.level-key-2 = '00000001' THEN STRING(inventory.qoh) ELSE "0"
+ "^" + IF inventory.level-key-2 = '00000002' THEN STRING(inventory.qoh) ELSE "0"
SKIP.
END.
because you accumulate invesntory.qoh in dependency of inventory.level-key-2 the ACCUMULATE stmt is not realy feasible so coding the accumulation manually would be the best choise
DEFINE VARIABLE loc1 AS INTEGER NO-UNDO.
DEFINE VARIABLE loc2 AS INTEGER NO-UNDO.
FOR EACH product-um NO-LOCK
WHERE product-um.gross-pkgd-weight <= 0.0000
,
EACH product NO-LOCK
WHERE product.product-key = product-um.product-key
AND product.can-be-sold = YES
,
EACH inventory NO-LOCK
WHERE inventory.product-key = product.product-key
AND inventory.product-code = product.product-code
AND inventory.qoh > 0
AND inventory.level = 2
,
EACH um NO-LOCK
WHERE um.um-key = product-um.um-key
and um.um = ip-um
BREAK
BY product.product-code:
CASE (inventory.level-key-2):
WHEN "00000001"
THEN loc1 = loc1 + inventory.qoh.
WHEN "00000002"
THEN loc2 = loc2 + inventory.qoh.
END CASE.
IF LAST-OF(product.product-code)
THEN DO:
MESSAGE
product.product-code + "^" +
product.product-name + "^" +
um.um-code + "^" +
STRING(product-um.gross-pkgd-weight) + "^" +
STRING(loc1) + "^" +
STRING(loc2)
SKIP.
ASSIGN
loc1 = 0
loc2 = 0
.
END.
END.
BREAK BY tells the compiler to mark when the FOR EACH has come to the start or end of a break group.To detect these changes you'll need to use one of these functions to detect that change: FIRST(table.field), FIRST-OF(table.field), LAST(table.field), and LAST-OF(table.field).
Once the required function returns true, you can use the ABL supplied functions like ACCUMULATE, COUNT, TOTAL, etc. to display the desired results. Personally I find the concepts a bit hard to get my head around, so I declare some local variables and do the totals that way.

In a recursive function, how does a series of returns get assembled back into a single result?

I'm trying to understand what's going on in this recursive function. It reverses a String, but I don't quite get how these separate return calls get assembled into one string at the end.
def reverse(string: String): String = {
if (string.length() == 0)
return string
return reverse(string.substring(1)) + string.charAt(0)
}
I've analysed the function by adding in print statement, and while I kind of understand how it works (conceptually), I don't understand, well... how it works.
For instance, I know that each cycle of recursion pushes things into the stack.
So, I would expect reverse("hello"), to become a stack of
o
l
l
e
h
But it must be more complex than that, as the recursive call is return reverse(string.substring(1)) + string.charAt(0). So is the stack actually
o,
l, o
l, lo
e, llo
H, ello
?
How does that get turned into the single string we expect?
The stack contains all local variables, as well as any temporary result in an expression where the recursion appears (though those are pushed on the stack even without recursion, because JVM is a stack machine) and, of course, the point where the code execution should resume on return.
In this case, the recursive call is the whole expression (that is, nothing is computed before reverse on the expression it appears). So the only thing besides the code pointer is string. At the deepest level of recursion, the stack will look like this:
level string
5 (empty string)
4 o
3 lo
2 llo
1 ello
0 hello
So when the call to level 5 returns, level 4 will finish computing the expression that reverse is a part of, reverse(string.substring(1)) + string.charAt(0). The value of reverse(string.substring(1)) is the empty string, and the value of string.charAt(0) is o (since the value of string on level 4 is o). The result is o, which is returned.
On level 3, it concatenates the return value from level 4 (o) with string.charAt(0) for string equal to lo, which is l, resulting in ol.
On level 2, it concatenates ol with l, giving oll.
Level 1 concatenates oll with e, returning olle.
Level 0, finally, concatenates olle with h, returning olleh to its caller.
On a final note, when a call is made, what is pushed into the stack is the return point for the code and the parameters. So hello is the parameter to reverse, which is pushed on the stack by reverse's caller.
Use the substitution model to work through the problem:
reverse("hello") =
(reverse("ello") + 'h') =
((reverse("llo") + 'e') + 'h') =
(((reverse("lo") + 'l') + 'e') + 'h') =
((((reverse("o") + 'l') + 'l') + 'e') + 'h') =
(((((reverse("") + 'o') + 'l') + 'l') + 'e') + 'h') =
((((("" + 'o') + 'l') + 'l') + 'e') + 'h') =
(((("o" + 'l') + 'l') + 'e') + 'h') =
((("ol" + 'l') + 'e') + 'h') =
(("oll" + 'e') + 'h') =
("olle" + 'h') =
"olleh"
Аdd a couple of tips on how to make your code better:
Don't use return in functions because function automaticaly return result of last evaluated line
String is a List of Char's, and you can replace string.substring(1) => string.tai, and string.charAt(0) => string.head
If you call immutable method, like length, size or etc you can omit the parentheses string.length() === string.length
That last version of your single line function:
def reverse(s: String): String = if (s.size == 0) s else reverse(s.tail) + s.head

how to solve this boolean algrbra expression

I would like help simplifying this boolean algebra expression:
B*C + ~A*~B + ~A*~C => A*B*C + ~A
I need to know the steps of how to simplify it to the ABC + ~A
'*' indicates "AND"
'+' indicates "OR"
"~A" indicates "A NOT"
Any help would be appreciated!
Thank you!
For a better view, i'll skip * for conjunction, and use ' for negation.
First you shall expand the 2 term disjunctions: Expand B*C , A'*B' and A'*C'
1) (A + A')BC + A'B'(C + C') + A'(B + B')C'
now distribute the parentheses.
2) ABC + A'BC + A'B'C + A'B'C' + A'BC' + A'B'C'
the fourth term and the last term are the same, A'B'C', so ignore one of them since p + p = p or you can expand the situation for your needs (might be needed for some situations) as in p+p+p+p+....+p = p
3) So now, lets try to search for common terms. See the 2nd term and 5th term, A'BC and A'BC'. Take common parenthesis, A'B(C+C') => A'B.
Do the same for 3rd term and the 4th term, A'B'C and A'B'C'. A'B'(C+C') => A'B' since X+X' = 1.
now we have:
ABC + A'B + A'B'
4) take common parenthesis again, 2nd and 3rd term: A'(B+B')
There you have ABC + A'
BC + A'B' + A'C' => ABC + A'