Tickperplant subscription by sym sending single records not tables by editing .u.pub - kdb

I have a ticker plant that has the schema:
quote:([]time:(); sym:();expiration:();mtype:();price:();cond:();exchange:();volume:())
trade:([]time:(); sym:();expiration:();mtype:();price:();cond:();exchange:();volume:())
rfills:([]time:();sym:();expiration:();tag:();price:();volume:())
I then double check the schema by doing
meta trade
I subscribe to the tickerplant as such getting the trade table
h(`.u.sub;`trade;`)
But when I try to specify a symbol from sym by doing
h(`.u.sub;`trade;`ZB)
No records are being pushed, This is odd because when I subscribe to all syms you can see that `ZB is definitely sym being pushed as shown below after setting upd to show
Figured out the above question, as a single record was being pushed not a table or key-value pair.This is what is going on.
So I was publishing a single record not a table from qSharp:
string giantstring2 = ".u.upd[" + "`trade;" + qdatetime + "," + rsymbol + "," + rexp + "," + qtype + "," + qprice + "," + qcondition + "," + qexchange + "," + qvolume + " ]";
q.Async(giantstring2);
I then set .u.upd to be .u.pub . So clients are recieve the single record but since its not a table nor a key value pair it doesn't grab the sym. So then I decided to change .u.upd to be
.u.upd:{[tabname;tabdata]
tabname insert tabdata;
tabd1::tabdata;
r2:: last (eval tabname);
.u.pub[tabname; r2];
};
So now subscribing by sym works however there is another issue, now it keeps publishes the entire table not just the record. Thinking of how to make this do what I want however I'm not sure how to go about it. Upon investigation of the .u.pub function
{[t;x]{[t;x;w]if[count x:sel[x]w 1;(neg first w)(`upd;t;x)]}[t;x]each w t}
It looks like it goes through the table and publishes each record. I assume I can edit this to just submit the last record and everything should work how I expect it to. Although I am unsure how to that. Any ideas? I assume I need to change the each w t part to only grab the last record and not the entire table

Related

How do I get unique values of one column based on another column using the insert database query in Anylogic?

How do I get unique values of one column based on another column using the query?
I tried using
(double)selectFrom(tasks).where(tasks.tasks_type.eq()).uniqueResult(tasks.task_cycle_time_hr);
I want to automate this and make sure that all the values of task_type are being read and a unique value for each of the tasks_type is being returned!
For all the values in the column task_type, I require a unique value from the column task_cycle_time_hr.
I don't really understand why you're trying to do this in one query.
If you want to get the cycle time (task_cycle_time_hr column) for each task type (tasks_type column), just do queries in a loop for each possible tasks_type value. If you don't know those a priori, do queries for each value returned by a query of the task type values, which would look something like
for (String taskType : selectFrom(tasks).list(tasks.tasks_type)) {
double cycleTime = (double) selectFrom(tasks)
.where(db_table.tasks_type.eq(taskType))
.firstResult(tasks.task_cycle_time_hr);
traceln("Task type " + taskType + ", cycle time " + cycleTime);
}
But this just amounts to querying all rows and reading the task type and cycle time values from each, so you wouldn't normally do it like this: you'd just have a single query looping through all the full rows instead...
List<Tuple> rows = selectFrom(tasks).list();
for (Tuple row : rows) {
traceln("Task type " +
row.get(tasks.tasks_type) + ", cycle time " +
row.get(tasks.task_cycle_time_hr));
}
NB: I assume you don't have any rows with duplicate task types because then the whole exercise doesn't make sense unless you want only the first row for each task type value, or want some kind of aggregate (e.g., sum) of the cycle time values for each given task type. You were trying to use uniqueResult, which may mean you want to get a value if there is exactly one row (for a given task type) and 'no result otherwise', but uniqueResult throws an exception (errors) if there isn't exactly one row (so you can't use that directly like that). In that case one way (there are others, some probably slightly better) would be to do a count first to check; e.g. something like
for (String taskType : selectFrom(tasks).list(tasks.tasks_type)) {
int rowCount = (int) selectFrom(tasks)
.where(db_table.task.eq(taskType))
.count();
if (rowCount == 1) {
double cycleTime = (double) selectFrom(tasks)
.where(db_table.tasks_type.eq(taskType))
.firstResult(tasks.task_cycle_time_hr);
traceln("Task type " + taskType + ", unique cycle time " + cycleTime);
}
}
Import your excel sheet into the AnyLogi internal DB and then make use of the DB wizard that will take you step by step to write the code to retrieve the data you want
(double) selectFrom(data)
.where(data.tasks.eq("T1"))
.firstResult(data.task_cycle_time_hr)

idh_hist query is very slow while searching with date

I am trying to write a query to search thru MFG/PRO invoice table 'idh_hist' for specific date range. It is running very slow when added the date condition. But when I put off the date condition, it is very fast. Can you please suggest ways to write a query on idh_hist that runs reasonably faster with conditions.
Following is my query:
for each idh_hist no-lock where idh_domain = "d0002"
and idh_due_date = TODAY:
/* display code here... */
end.
Thanks in advance!
Database Index:
Flags Index Name Cnt Field Name
----- --------------------- ---- ---------------------
idh_fsm_type 4 + idh_domain
+ idh_fsm_type
+ idh_nbr
+ idh_line
pu idh_invln 4 + idh_domain
+ idh_inv_nbr
+ idh_nbr
+ idh_line
idh_part 4 + idh_domain
+ idh_part
+ idh_inv_nbr
+ idh_line
u oid_idh_hist 1 + oid_idh_hist
You do not appear to have an index that uses idh_due_date. You will need to add such an index.
The 4gl uses rules to select indexes based on the WHERE clause. The most important rule is that leading components of the index which have equality matches will be used.
The query you have shown only has one such match on idh_domain. So then tie breaker rules are applied. This will result in the idh_invln index being chosen.
As it is, to satisfy your query all records that match the "idh_domain" field need to be searched. (If you only have one domain that means that you are doing a table scan.)
You probably want to add an index on idh_domain and idh_due_date. That would be a perfect match for your query.

tsql comma delimited testing for value

I've been given a table with a few fields that hold comma-separated values (either blank or Y/N) like so (and the field name where this data is stored is People_Notified):
Y,,N,
,Y,,N
,,N,Y
Each 'slot' relates to a particular field value and I need to now include that particular field name in the string as well (in this case Parent, Admin, Police and Medical) but inserting a "N" if the current value is blank but leaving the existing Y's and N's in place. So for the above example, where there are four known slots, I would want a tsql statement to end up with:
Parent=Y,Admin=N,Police=N,Medical=N
Parent=N,Admin=Y,Police=N,Medical=N
Parent=N,Admin=N,Police=N,Medical=Y
I tried to use a combination of CHARINDEX and CASE but haven't figured a way to make this work.
js
Although a bit messy, in theory can be done in one statement:
select
'Parent=' +stuff((stuff((stuff(
substring((replace(
(','+(replace((replace(#People_Notified,',,,',',N,N,')),',,',',N,'))+','),',,',',N,')),2,7),7,0,
'Medical=')),5,0,'Police=')),3,0,'Admin=')
broken down is easier to follow:
declare #People_Notified varchar(100)=',,Y,Y' -- test variable
-- Insert Ns
set #People_Notified= (select replace(#People_Notified,',,,',',N,N,')) -- case two consecutive missing
set #People_Notified= (select replace(#People_Notified,',,',',N,')) -- case one missing
set #People_Notified= (select replace((','+#People_Notified+','),',,',',N,')) -- case start or end missing
set #People_Notified= substring(#People_Notified,2,7) -- remove extra commas added previously
-- Stuff the labels
select 'Parent=' +stuff((stuff((stuff(#People_Notified,7,0,'Medical=')),5,0,'Police=')),3,0,'Admin=')
If you're able to use XQuery in SQL Server, I don't think you need to get too complex. You could do something like this:
SELECT CONVERT(XML, REPLACE('<pn>' + REPLACE(People_Notified, ',', '</pn><pn>') + '</pn>', '<pn></pn>', '<pn>N</pn>')).query('
concat("Parent=", data(/pn[1])[1], ",Admin=", data(/pn[2])[1], ",Police=", data(/pn[3])[1], ",Medical=", data(/pn[4])[1])
')
FROM ...
Explanation: Construct an XML-like string out of the original delimited string by replacing commas with closing and opening tags. Add an opening tag to the start and a closing tag to the end. Replace each empty element with one containing "N". Convert the XML-like string into actual XML data so that you can use XQuery. Then just concatenate what you need using concat() and the right indexes for the elements' data.
Here's one way to do it:
;WITH cteXML (Id, Notified)
AS
(
SELECT Id,
CONVERT(XML,'<Notified><YN>'
+ REPLACE([notified],',', '</YN><YN>')
+ '</YN></Notified>') AS Notified
FROM People_Notified
)
select id,
'Parent=' + case Notified.value('/Notified[1]/YN[1]','varchar(1)') when '' then 'N' else Notified.value('/Notified[1]/YN[1]','varchar(1)') end + ',' +
'Admin=' + case Notified.value('/Notified[1]/YN[2]','varchar(1)') when '' then 'N' else Notified.value('/Notified[1]/YN[2]','varchar(1)') end + ',' +
'Police=' + case Notified.value('/Notified[1]/YN[3]','varchar(1)') when '' then 'N' else Notified.value('/Notified[1]/YN[3]','varchar(1)') end + ',' +
'Medical=' + case Notified.value('/Notified[1]/YN[4]','varchar(1)') when '' then 'N' else Notified.value('/Notified[1]/YN[4]','varchar(1)') end Notified
from cteXML
SQL Fiddle
Check this page out for an explanation of what the XML stuff is doing.
This page has a pretty thorough look at the various ways you can split a delimited string into rows.

Firebird 2.5.x. Extract column names and column datatypes of a result from stored procedure

I have a Firebird 2.5 database .As an example I have stored procedure with a name QRESULT which expected return is:
Parameter - DATATYPE
a - date
b - numeric(18,0)
c - integer
d - varchar(50)
and so on....
I use PHP - PDO to query the firebird database using the procedure QRESULT like this:
SELECT a,b,d from QRESULT() where a = "some value"
I need to run some query before QRESULT procedure and i need it to return the datatype of all the columns that QRESULT would return if it was ran. So i can help user to type proper value for my "where" clause.I know i can set that manually in the user interface, but in the real project there are lots of procedures and if there is a way i can make my filter interface generate dynamically i would be happy about that.If this is not possible for a stored procedure i can make it with select statements.I just need some lead.
The information you want is in the RDB$PROCEDURE_PARAMETERS table, basically what you need is query
SELECT r.RDB$PARAMETER_NAME ParName, F.RDB$FIELD_TYPE ParType
FROM RDB$PROCEDURE_PARAMETERS r
JOIN RDB$FIELDS F ON(F.RDB$FIELD_NAME = R.RDB$FIELD_SOURCE)
WHERE r.RDB$PROCEDURE_NAME = 'QRESULT'
AND r.RDB$PARAMETER_TYPE = 1
ORDER BY r.RDB$PARAMETER_TYPE, r.RDB$PARAMETER_NUMBER
Note that the SP name should be in upper case as this is how it is stored into system tables (unless you use quoted identifiers). If you want to get both input and output parameters the delete the r.RDB$PARAMETER_TYPE = 1 predicate from the WHERE (type 0 is input parameters and 1 is output).
The type returned by this query is integer id for the type, quick googling found this:
14,"TEXT "
7,"SHORT "
8,"LONG "
9,"QUAD "
10,"FLOAT "
27,"DOUBLE "
35,"TIMESTAMP "
37,"VARYING "
261,"BLOB "
40,"CSTRING "
45,"BLOB_ID "
12,"DATE "
13,"TIME "
16,"INT64 "
but if you want to have more precise type then see this SO post.

concatenate without losing thousands separator

I have a report that brings total sales and total probability sale.
The request was that this be shown in one table as "R"{totalamount}" (R"{totprobamount")".
So i added this together in a variable with the variable expression being
"R" + $F{Totalt} +" (R" + $F{Totalp} +")"
but by doing this the Thousands separator does not show anymore?
If you can add a field for each value you wouldn't do this with String concatenation but by using patterns on text field. add for each field in the properties panel a patter such as R #,##0.00.
if it has to be in a single field you'd need to add an expression to actually format the numbers in the desired way such as for example: "R" + new DecimalFormat("#,##.00").format($F{Totalt}) + " (R" + new DecimalFormat("#,##.00").format($F{Totalp}) + ")"
You can use the FORMAT function to have thousand separator.
FORMAT({totalamount} +{totprobamount},2)
This column become String column so you have to add this column separately , you cant use same column for integer value. Where 2 is for up to 2 decimal value.