I need to write a case when statement in db2. I am new, so I do not have much experience,sorry for that.
I have a column with different call numbers, each call number should contain 7 digits. (eg.AR78HJ8)
I need when the value is blank or "_______", (7 times _ ), the result to be 0,
and when I have a seven digits call number, (but not 7 times _ ) the result to be 1.
Also , there could be cases when the call number is 8, 6 or any other different then 7 digits. In this case I want to show the call number itself.
What I have written so far is
case when ab.call_number = '' then '0'
when ab.call_number = '_______' then '0'
else '1'
end as "Call number",
but in this case I assume that all other call numbers are always 7 digits.
What should I do?
Thanks a lot for your help!
Try this as is:
WITH TAB (CALL) AS
(
VALUES
'1234567'
, ''
, ' '
, 'AR78HJ8'
, '12345678'
)
SELECT CALL
,
CASE
WHEN CALL = '' THEN '0'
WHEN LENGTH(TRANSLATE(CALL, '', '0123456789', '')) = 0 AND LENGTH(CALL) = 7 THEN '1'
ELSE CALL
END AS "Call number"
FROM TAB;
The result is:
|CALL |Call number|
|--------|-----------|
|1234567 |1 |
| |0 |
| |0 |
|AR78HJ8 |AR78HJ8 |
|12345678|12345678 |
Related
. as $index | 1 as $runner | label $out | range($index; 20)
| if (. == 10) then break $out else "dx" + ($runner|tostring) | ($runner+1) as $runner | . end
for input 1
I would like to update $runner variable value while looping using range.
demo
Thanks in advance
You cannot "update" a variable in the same context, you can only shadow it by setting its value for a new context, based on the previous.
That said, range already iterates in your sense, no need to +1 anywhere. Store the value of the iteration itself to the $runner variable, and you can use it as envisioned. To filter out certain values, use select, no need for label and break.
. as $index | range($index; 20) as $runner
| select($runner < 10) | "dx\($runner)"
"dx1"
"dx2"
"dx3"
"dx4"
"dx5"
"dx6"
"dx7"
"dx8"
"dx9"
Demo
If you don't need the variables elsewhere, you can even iterate without variables. A condensed version ofthe above:
range(.; 20) | "dx\(select(. < 10))"
Demo
Given a dynamic field, say, milestones, it has value like: {"ta": 1655859586546, "tb": 1655859586646},
How do I print a table with columns like "ta", "tb" etc, with the single row as unixtime_milliseconds_todatetime(tolong(taValue)), unixtime_milliseconds_todatetime(tolong(tbValue)) etc.
I figured that I'll need to write a function that I can call, so I created this:-
let f = view(a:string ){
unixtime_milliseconds_todatetime(tolong(a))
};
I can use this function with a normal column as:- project f(columnName).
However, in this case, its a dynamic field, and the number of items in the list is large, so I do not want to enter the fields manually. This is what I have so far.
log_table
| take 1
| evaluate bag_unpack(milestones, "m_") // This gives me fields as columns
// | project-keep m_* // This would work, if I just wanted the value, however, I want `view(columnValue)
| project-keep f(m_*) // This of course doesn't work, but explains the idea.
Based on the mv-apply operator
// Generate data sample. Not part of the solution.
let log_table = materialize(range record_id from 1 to 10 step 1 | mv-apply range(1, 1 + rand(5), 1) on (summarize milestones = make_bag(pack_dictionary(strcat("t", make_string(to_utf8("a")[0] + toint(rand(26)))), 1600000000000 + rand(60000000000)))));
// Solution Starts here.
log_table
| mv-apply kv = milestones on
(
extend k = tostring(bag_keys(kv)[0])
| extend v = unixtime_milliseconds_todatetime(tolong(kv[k]))
| summarize milestones = make_bag(pack_dictionary(k, v))
)
| evaluate bag_unpack(milestones)
record_id
ta
tb
tc
td
te
tf
tg
th
ti
tk
tl
tm
to
tp
tr
tt
tu
tw
tx
tz
1
2021-07-06T20:24:47.767Z
2
2021-05-09T07:21:08.551Z
2022-07-28T20:57:16.025Z
2022-07-28T14:21:33.656Z
2020-11-09T00:54:39.71Z
2020-12-22T00:30:13.463Z
3
2021-12-07T11:07:39.204Z
2022-05-16T04:33:50.002Z
2021-10-20T12:19:27.222Z
4
2022-01-31T23:24:07.305Z
2021-01-20T17:38:53.21Z
5
2022-04-27T22:41:15.643Z
7
2022-01-22T08:30:08.995Z
2021-09-30T08:58:46.47Z
8
2022-03-14T13:41:10.968Z
2022-03-26T10:45:19.56Z
2022-08-06T16:50:37.003Z
10
2021-03-03T11:02:02.217Z
2021-02-28T09:52:24.327Z
2021-04-09T07:08:06.985Z
2020-12-28T20:18:04.973Z
9
2022-02-17T04:55:35.468Z
6
2022-08-02T14:44:15.414Z
2021-03-24T10:22:36.138Z
2020-12-17T01:14:40.652Z
2022-01-30T12:45:54.28Z
2022-03-31T02:29:43.114Z
Fiddle
I have Sessions table
Sessions
|Timespan|Name |No|
|12:00:00|Start|1 |
|12:01:00|End |2 |
|12:02:00|Start|3 |
|12:04:00|Start|4 |
|12:04:30|Error|5 |
I need to extract from it duration of each session using KQL (but if you could give me suggestion how I can do it with some other query language it would be also very helpful). But if next row after start is also start, it means session was abandoned and we should ignore it.
Expected result:
|Duration|SessionNo|
|00:01:00| 1 |
|00:00:30| 4 |
You can try something like this:
Sessions
| order by No asc
| extend nextName = next(Name), nextTimestamp = next(timestamp)
| where Name == "Start" and nextName != "Start"
| project Duration = nextTimestamp - timestamp, No
When using the operator order by, you are getting a Serialized row set, which then you can use operators such as next and prev. Basically you are seeking rows with No == "Start" and next(Name) == "End", so this is what I did,
You can find this query running at Kusto Samples open database.
let Sessions = datatable(Timestamp: datetime, Name: string, No: long) [
datetime(12:00:00),"Start",1,
datetime(12:01:00),"End",2,
datetime(12:02:00),"Start",3,
datetime(12:04:00),"Start",4,
datetime(12:04:30),"Error",5
];
Sessions
| order by No asc
| extend Duration = iff(Name != "Start" and prev(Name) == "Start", Timestamp - prev(Timestamp), timespan(null)), SessionNo = prev(No)
| where isnotnull(Duration)
| project Duration, SessionNo
I have two tables which I export from my video editing suite, one ("MediaPool") containing a row for each media file imported into the project, another ("Montage") for the portions of that file used in a specific edit. The fields that are associated between the two are MediaPool.FileName and Montage.Name, which are very similar (Filename only adds the file extension).
# MediaPool
Filename | Take
---------------------------------
somefile.mp4 | Getty
file2.mov | Associated Press
file3.mov | Associated Press
and
# Montage
Name | RecordIn | RecordOut
------------------------------------------
somefile | 01:01:01:01 | 01:01:20:19
somefile | 01:05:15:23 | 01:05:16:10
somefile | 01:25:19:10 | 01:30:16:04
file2 | 01:30:11:10 | 01:31:18:12
file2 | 01:40:15:22 | 01:42:21:17
The tables contain many more columns of course, but only the above is relevant.
Only the "MediaPool" table contains the field called "Take" which designates the file's copyright holder (long story). It can't be included in the "Montage" export. I needed to calculate the total duration of footage used from each source, by subtracting the RecordIn timecode from RecordOut and adding each result. This turned out to be more complicated than I expected, as I have some notions of programming but almost none when it comes to SQL (sqlite in my case).
I managed to come up with the following, which works fine and runs in under 4 seconds. However, from the little programming I've done, it seems overlong and very inelegant. Is there a shorter way to achieve this?
BTW, I'm using 25 fps timecode and I can't use LPAD in sqlite.
SELECT
Source,
SUBSTR('00' || CAST(DurationFrames/(60*60*25) AS TEXT), -2, 2) || ':' ||
SUBSTR('00' || CAST(DurationFrames%(60*60*25)/(60*25) AS TEXT), -2, 2) || ':' ||
SUBSTR('00' || CAST(DurationFrames%(60*60*25)%(60*25)/25 AS TEXT), -2, 2) || ':' ||
SUBSTR('00' || CAST(DurationFrames%(60*60*25)%(60*25)%25 AS TEXT), -2, 2)
AS DurationTC
FROM
(
SELECT
MediaPool.Take AS Source,
Montage.RecordIn,
Montage.RecordOut,
SUM(CAST(SUBSTR(Montage.RecordOut, 1, 2) AS INT)*3600*25 +
CAST(SUBSTR(Montage.RecordOut, 4, 2) AS INT)*60*25 +
CAST(SUBSTR(Montage.RecordOut, 7, 2) AS INT)*25 +
CAST(SUBSTR(Montage.RecordOut, 10, 2) AS INT) -
CAST(SUBSTR(Montage.RecordIn, 1, 2) AS INT)*3600*25 -
CAST(SUBSTR(Montage.RecordIn, 4, 2) AS INT)*60*25 -
CAST(SUBSTR(Montage.RecordIn, 7, 2) AS INT)*25 -
CAST(SUBSTR(Montage.RecordIn, 10, 2) AS INT))
AS DurationFrames
FROM
MediaPool
JOIN
Montage ON MediaPool.FileName LIKE '%' || Montage.Name || '%'
GROUP BY
Take
ORDER BY
Take
)
Here's a simplified query that produces the same results as yours on your test data. Mostly it uses printf() instead of a bunch of string concatenation and substr()s, and uses strftime() to calculate the total seconds of the hours minutes seconds part of the timecode:
WITH frames AS
(SELECT Take, sum((strftime('%s', substr(RecordOut,1,8))*25 + substr(RecordOut,10))
- (strftime('%s', substr(RecordIn,1,8))*25 + substr(RecordIn,10)))
AS DurationFrames
FROM MediaPool
JOIN Montage ON MediaPool.Filename LIKE Montage.Name || '.%'
GROUP BY Take)
SELECT Take AS Source
, printf("%02d:%02d:%02d:%02d", DurationFrames/(60*60*25),
DurationFrames%(60*60*25)/(60*25),
DurationFrames%(60*60*25)%(60*25)/25,
DurationFrames%(60*60*25)%(60*25)%25)
AS DurationTC
FROM frames
ORDER BY Take;
I need to search few patterns from a column using regular expression in Teradata.
One of the example is mentioned below:
SELECT
REGEXP_SUBSTR(
REGEXP_SUBSTR('1-2-3','([0-9] *- *[0-9] *- *[0-9])',1, 1, 'i'),
'([0-9] *- *[0-9] *- *[0-9])',
1, 1, 'i'
) AS Tmp,
REGEXP_SUBSTR(
tmp,
'(^[0-9])',1,1,'i') || '-' || REGEXP_SUBSTR(tmp,'([0-9]$)',
1, 1, 'i'
) AS final_exp
;
In the above expression, I am extracting "1-3" out of a pattern like "1-2-3". Now the patterns can be anything like: 1-2-3-4-5 or 1-2,3 or 1&2-3 or 1-2,3 &4.
Is there any way that I can generalize the search pattern in regular expression like [-,&]* will only search for occurrence of this characters in order, but the characters can be present in any order in the data.
Few examples mentioned below,need is to fetch all the desired result set using a single pattern serch in expression.
Column name ==> Result
abc 1-2+3- 4 ==> 1-4
def 10,12 & 13 ==> 10-13
ijk 1,2,3, and 4 lmn ==> 1-4
abc1-2 & 3 def ==> 1-3
ikl 11 &12 -13 ==> 11-13
oAy$ 7-8 and 9 ==> 7-9
RegExp_Substr(col, '(\d+)',1, 1, 'c') || '-' ||
RegExp_Substr(col, '(\d+)(?!.*\d)',1, 1, 'c')
(\d+) = first number
(\d+)(?!.*\d) = last number (a number not followed by another number)
There's also no need for those optional parameters, because it's using the defaults anyway:
RegExp_Substr(col, '(\d+)') || '-' ||
RegExp_Substr(col, '(\d+)(?!.*\d)')