kdb: convert 1x1 table to an atom - sql

How do I convert a table to an atom? I have a 1x1 table with a header. I want to get rid of the header and just have the number so that I do things like anotherTable*thisNumber and so on.
I've tried:
(raze raze tableName)
but this gives me: enlist 10.5, how do I get 10.5 (as a number)?

q)t:([] head:enlist 1)
q)t
head
----
1
q)first exec head from t
1
q) // or the shortest way
q)t[`head]0
1
q)type first exec head from t
-7h
q)100*first exec head from t
100
q)first t`head
1
q)raze/[t]0
1

Think you can use over and indexing to do this:
q)raze/[([]a:1#1)]0
1

For Ryan example:
t:([] head:enlist 1)
We can also simply do,
first t`head

Related

Ordering by sub string of a field with OPNQRYF

I have a requirement where I need to change the order in which records are printed in a Report. I need to order the records by a substring of a field of the records.
There is an OPNQRYF as below before the call to the report RPG is made:
OVRDBF FILE(MOHDL35) SHARE(*YES)
BLDQRYSLT QRYSLT(&QRYSLT) +
SELECT((CHARDT *GE &FRDATE F2) +
(CHARDT *LE &TODATE F2) +
(HDPLVL *EQ 'FS' F2) +
(HDMPLT *EQ &PLANT F2))
OPNQRYF FILE((*LIBL/MOHDL35)) +
QRYSLT(&QRYSLT) +
KEYFLD(*FILE) +
MAPFLD((ZONEDT HDAEDT *ZONED 8 0) +
(CHARDT ZONEDT *CHAR 8))
One way I see how to do this is to do a RUNSQL to create a temp table in qtemp with the MOHDL35 records in the required order. The substr SQL function would help to achieve this much easier. This should have the same structure as that of MOHDL35 (FIELD NAMES, RECORD FORMAT)
Then replace the use of this file in the RPG program with the newly created table name. I havent tried this yet, but would this work? does it sound like a good idea? Are there any better suggestions?
You can do that with OPNQRYF by using the MAPFLD parameter like this:
OPNQRYF FILE((JCVCMP))
KEYFLD((*MAPFLD/PART))
MAPFLD((PART '%SST(VCOMN 2 5)'))
The fields in JCVCOMN are now sorted like this:
VENNO VCMTP VCMSQ VCOMN
----- ----- ----- -------------------------
1,351 ICL 3 Let's see what wow
1,351 ICL 1 This is a test
1,351 NDA 2 another comment
1,351 NDA 1 more records
Notice that the records are sorted by the substring of VCOMN starting with the second character.
So here is your OPNQRYF with multiple key fields specified
OPNQRYF FILE((*LIBL/MOHDL35))
QRYSLT(&QRYSLT)
KEYFLD((*MAPFLD/CHARDT) (*MAPFLD/HDPROD))
MAPFLD((ZONEDT HDAEDT *ZONED 8 0) (CHARDT ZONEDT *CHAR 8)
(HDPROD '%SST(HDPROD 1 2) *CAT %SST(HDPROD 10 12)
*CAT %SST(HDPROD 13 16)'))
Some notes: I am guessing that HDAEDT is a PACKED number. If so, you don't need to map it to a ZONED number just to get it to a character value. If you need the ZONED value, that is ok (but PACKED should work just as well). Otherwise, you can just use:
MAPFLD((CHARDT HDAEDT *CHAR 8))
Also in your OVRDBF, you need to make sure you choose the correct Override Scope OVRSCOPE. The IBM default is OVRSCOPE(*ACTGRPDFN). OPNQRYF also has a scope OPNSCOPE. You need to make sure that the OVRSCOPE, the OPNSCOPE, and the program using the table all use the same activation group. There are a lot of different combinations. If you can't make it work, you can always change them all to *JOB, and that will work. But there is nothing intrinsic about OPNQRYF that prevents it from working from a CLP.
I would try creating a view with all the table fields plus the substring'd column, and then use OPNQRYF with that instead of the table, specifying the substring'd column as the KEYFLD. That would probably be simpler (& potentially quicker) than copying the whole lot into QTEMP every time.

5 characters string ID like Northwind CustomerID

I am looking to get a 5 character long string compiled from a string name, just like it is in MS Northwind sample database (Customers.CustomerID):
CustomerID CompanyName
----- ----------------------------------
ALFKI Alfreds Futterkiste
ANATR Ana Trujillo Emparedados y helados
ANTON Antonio Moreno Taquería
AROUT Around the Horn
BERGS Berglunds snabbköp
BLAUS Blauer See Delikatessen
BLONP Blondesddsl pere et fils
BOLID Bólido Comidas preparadas
BONAP Bon app'
BOTTM Bottom-Dollar Markets
BSBEV B's Beverages
... ...
So the ID (code) is not totally random, it somehow resembles the content of the string name. Obviously, duplicity is forbidden, the code has to be unique. Let's assume:
DECLARE #StrCode NCHAR(5)
I'd start with thinging along theese lines - I would create a scalar function to check duplicities which would return 0 for no duplicities and 1 for found duplicities, the core check would be simply counting lines of the provided string code:
SELECT COUNT(ID) FROM MyTable WHERE StrCode = #StrCode
And then in an another function (input = StringName, output = #StrCode) I'd try few approaches, from the most readable to the least readable, and check each attempt for a duplicity along the way:
SELECT #StrCode =
CASE
WHEN dbo.CheckForDuplicity(SUBSTRING(#StringName,1,6)) = 0
THEN SUBSTRING(#StringName,1,6) -- get start of the string name
WHEN CHARINDEX(' ',#StringName) > 0 AND dbo.CheckForDuplicity(CONCAT(SUBSTRING(#StringName,1,3),SUBSTRING(#StringName,CHARINDEX(' ',#StringName)+1,2))) = 0
THEN CONCAT(SUBSTRING(#StringName,1,3),SUBSTRING(#StringName,CHARINDEX(' ',#StringName)+1,2)) -- get 3 chars from the 1st word and 2 chars from the 2nd
WHEN dbo.CheckForDuplicity(CONCAT(SUBSTRING(#StringName,1,3),SUBSTRING(#StringName,LEN(#StringName)-3,2))) = 0
THEN CONCAT(SUBSTRING(#StringName,1,3),SUBSTRING(#StringName,LEN(#StringName)-3,2)) -- get first 3 chars and last 2 chars
-- possibly other approaches...
END
So the first one would get accepted. But there may be a lot better approaches I'm not aware of...
This is only a concept. Is this a good idea?
And what about using this StringCode as a primary key, as they do in Northwind? Wouldn't this string key slow down the things, in comparison to INT key?

Create table name in Hive using variable subsitution

I'd like to create a table name in Hive using variable substitution.
E.g.
SET market = "AUS";
create table ${hiveconf:market_cd}_active as ... ;
But it fails. Any idea how it can be achieved?
You should use backtrics (``) for name for that, like:
SET market=AUS;
CREATE TABLE `${hiveconf:market}_active` AS SELECT 1;
DESCRIBE `${hiveconf:market}_active`;
Example run script.sql from beeline:
$ beeline -u jdbc:hive2://localhost:10000/ -n hadoop -f script.sql
Connecting to jdbc:hive2://localhost:10000/
...
0: jdbc:hive2://localhost:10000/> SET market=AUS;
No rows affected (0.057 seconds)
0: jdbc:hive2://localhost:10000/> CREATE TABLE `${hiveconf:market}_active` AS SELECT 1;
...
INFO : Dag name: CREATE TABLE `AUS_active` AS SELECT 1(Stage-1)
...
INFO : OK
No rows affected (12.402 seconds)
0: jdbc:hive2://localhost:10000/> DESCRIBE `${hiveconf:market}_active`;
...
INFO : Executing command(queryId=hive_20190801194250_1a57e6ec-25e7-474d-b31d-24026f171089): DESCRIBE `AUS_active`
...
INFO : OK
+-----------+------------+----------+
| col_name | data_type | comment |
+-----------+------------+----------+
| _c0 | int | |
+-----------+------------+----------+
1 row selected (0.132 seconds)
0: jdbc:hive2://localhost:10000/> Closing: 0: jdbc:hive2://localhost:10000/
Markovitz's criticisms are correct, but do not produce a correct solution. In summary, you can use variable substitution for things like string comparisons, but NOT for things like naming variables and tables. If you know much about language compilers and parsers, you get a sense of why this would be true. You could construct such behavior in a language like Java, but SQL is just too crude.
Running that code produces an error, "cannot recognize input near '$' '{' 'hiveconf' in table name".(I am running Hortonworks, Hive 1.2.1000.2.5.3.0-37).
I spent a couple hours Googling and experimenting with different combinations of punctuation, different tools ranging from command line, Ambari, and DB Visualizer, etc., and I never found any way to construct a table name or a field name with a variable value. I think you're stuck with using variables in places where you need a string literal, like comparisons, but you cannot use them in place of reserved words or existing data structures, if that makes sense. By example:
--works
drop table if exists user_rgksp0.foo;
-- Does NOT work:
set MY_FILE_NAME=user_rgksp0.foo;
--drop table if exists ${hiveconf:MY_FILE_NAME};
-- Works
set REPORT_YEAR=2018;
select count(1) as stationary_event_count, day, zip_code, route_id from aaetl_dms_pub.dms_stationary_events_pub
where part_year = '${hiveconf:REPORT_YEAR}'
-- Does NOT Work:
set MY_VAR_NAME='zip_code'
select count(1) as stationary_event_count, day, '${hiveconf:MY_VAR_NAME}', route_id from aaetl_dms_pub.dms_stationary_events_pub
where part_year = 2018
The qualifies should be removed
You're using the wrong variable name
SET market=AUS; create table ${hiveconf:market}_active as select 1;

How to find two strings in a CLOB column?

Ive tried many queries to find... just one word and I can´t even make that.
Its a DB2 database Im using com.ibm.db2.jcc.DB2Driver
This brings me info:
select *
from JL_ENR
where id_ws = '002'
and dc_dy_bsn = '2014-08-25'
and ai_trn = 2331
the JL_TPE column is the CLOB column where I want to find two strings in that search result ( and dc_dy_bsn = '2014-08-25'
and ai_trn = 2331 ).
So first I tried with one:
select
dbms_lob.substr(clob_column,dbms_lob_instr(JL_TPE,'CEMENTO'),1)
from
JL_ENR
where
dbms_lob.instr(JL_TPE,'CEMENTO')>0;
didnt work
SELECT * FROM JL_ENR WHERE dbms_lob.instr(JL_TPE,'CEMENTO')>0
and ai_trn = 2331
and dc_dy_bsn = '2014-08-25'
didnt work
Select *
From JL_ENR
Where NOT
DBMS_LOB.INSTR(JL_TPE, 'CEMENTO', 1, 1) = 0;
didn´t work
Could someone explain me how to find two strings please?
Or a tutorial link where it is explained how to make it work...
Thanks.
Can you provide some sample data and the version you are using? Your example should work (tested on v10.5.0.1):
db2 "create table test ( x int, y clob(1M) )"
db2 "insert into test (x,y) values (1,cast('The string to find is CEMENTO, how do we do that?')"
db2 "insert into test (x,y) values (2,cast('The string to find is CEMENT, how do we do that?' as clob))"
db2 "select x, DBMS_LOB.INSTR(y, 'CEMENTO', 1) from test where DBMS_LOB.INSTR(y, 'CEMENTO', 1) > 0"
X 2
----------- -----------
1 23
1 record(s) selected.
I had to search for a specific value in the where clause. I used TEXTBLOB LIKE '%Search value%' and it worked! This was for db2 in a CLOB(536870912) column.

sql to set an xml value

I'm a novice in mySql.
I'm trying to replace a value in the xml column of my table.
my select method works.
SELECT * FROM `comics` WHERE ExtractValue(xml,'comic/pageNumber') = 6
my replace method doesn't. I've been searching for the correct syntax for a bit now...
SET xml.modify(
replace value of ('comic/pageNumber') with 5
)
some background:
this situation comes up when i delete a comic page.
it leaves a gap in the page numbers, after which i would either:
iterate through all the comics and remove any gaps in the page numbers.
or
iterate through all comics with pageNumber larger than the deleted page, and reduce their pageNumber by 1.
How about
UPDATE comics
SET xml = UpdateXML(xml,'comic/pageNumber', '<pageNumber>5</pageNumber>')
WHERE ExtractValue(xml,'comic/pageNumber') = 6
Tested on MySQL version 5.1
UPDATE `comics`
SET xml = UpdateXML(xml,
'comic/pageNumber',
concat('<pageNumber>',(ExtractValue(xml,'comic/pageNumber')+1),'</pageNumber>'))
WHERE ExtractValue(xml,'comic/pageNumber') >= 1
You'd be better off actually storing the fields in the table, rather than a single field with xml in it. Then the following would work. Otherwise there's not much point using a relational database at all.
BEGIN;
DELETE FROM `comics`
WHERE `comicID` = :id AND `pageNumber` = :page;
UPDATE `comics` SET `pageNumber` = `pageNumber` - 1
WHERE `comicID` = :id AND `pageNumber` > :page;
COMMIT;