RE: [firebird-support] Gbaked and restored database larger than the original?

2015-07-08 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Take a look here: http://www.firebirdfaq.org/faq361/

I'd add that restore also has a -use_all_space option. If you don't specify 
this, then pages are filled to approximately 80% (80% is preferable over 100% 
unless it is a read-only database). See 
http://www.firebirdsql.org/manual/gbak-cmdline.html or 
http://www.firebirdsql.org/manual/gfix-pagespace.html for more information.

Set

-Original Message-
From: firebird-support@yahoogroups.com 
[mailto:firebird-support@yahoogroups.com] 
Sent: 8. juli 2015 11:48
To: firebird-support@yahoogroups.com
Subject: [firebird-support] Gbaked and restored database larger than the 
original?

Hi,

Just for my cursiosity and for a better understanding of Firebird: what can be 
a possible reason for a gbaked and restored (to a different file) database 
being _larger_ than the original one?
I've got a db of size 104521728 bytes. I do gbak -B -T database.fdb 
database.gbk, then gbak -C database.gbk newdatabase.fdb. The size of 
newdatabase.fdb is 104751104 (~ 200kB more).
I'm the only one messing with these databases, the platform is Linux x64, 
Firebird 2.5.2, all operations performed on the same machine, in the same file 
system. Before the backup-restore, a quite large chunk of metadata was 
added/altered in the original database (procedures, fields), which is the only 
clue I can think of at the moment (adding a default value to a field which had 
none?).
It's quite obvious why a restored database might be smaller than the original 
one (no garbage), but the other way around is a bit puzzling.
Both databases seem to work fine, so I'm in no trouble, but my ignorance in 
this matter bothers me nonetheless ;) I'd be grateful for any plausible 
explanations.

thanks in advance and best regards
Tomasz



Posted by: Tomasz Tyrakowski t.tyrakow...@sol-system.pl


++

Visit http://www.firebirdsql.org and click the Documentation item on the main 
(top) menu.  Try FAQ and other links from the left-side menu there.

Also search the knowledgebases at http://www.ibphoenix.com/resources/documents/ 

++


Yahoo Groups Links





SV: [firebird-support] general question: calculated fileds vs performance

2015-07-07 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hello! Generally speaking, regarding performance, is expensive having 
calculated fields?

Not complex ones, I mean this type of thing:



... COMPUTED BY (cast(qty * price * tax / 100 as money 2))

So far I don't notice any difference but I'd like to hear opinions about 
whether is a good

idea using them.



Probably having a real field, maintained with a trigger is better? I don't 
like having redundant

data in my database, but I'm note sure what is the better option: waste a bit 
of space or

(probably) decrease performance??

?
I've heard (don't remember who said it, and since I don't use calculated fields 
much myself, I cannot tell how reliable this information is) that calculated 
fields ought only to refer to the current record, i.e. not a different table or 
different record in the same table. So, as long as qty, price and tax all are 
part of the same record as your COMPUTED BY value, this ought to be fine. If 
they are stored in different lookup tables, then a view or a trigger maintained 
field may be preferrable.

Hopefully, others will verify this or tell that I'm wrong.

Set


RE: [firebird-support] Get ID of record with minsort

2015-06-25 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I have a table with one ID-Column and one Sort-Column.

I need the ID from the record with the lowest sort-number.
Sortnumbers are not unique (can be doubled).

Can I do this with one SQL-Statement?

If you want one row returned:

Select ID_column
From Table
Order by Sort_Column
Rows 1

If you want all rows returned:

Select ID_column
From Table t1
Where not exists(select * from Table t2 where t1.Sort  t2.Sort)

Alternatively, you could use

With tmp(Sort) as
(select min(Sort) from table)
Select t.ID_Column
From tmp
Join table t on tmp.Sort = t.Sort

Set


Re: [firebird-support] Soc Sec No comparison using Firebird

2015-06-24 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Greetings All,

I would like to pass into a stored procedure two social security numbers for 
comparison and have the result tell me if one character has changed, 
or if two characters were switched or if it does not compare at all.

Has anyone done anything like this they could share?  Or is it even possible?

Never done anything similar before, but strictly speaking, the following would 
answer your question:

execute block (ss1 varchar(20) = :ss1, ss2 varchar(20) = :ss2) returns 
(comparison varchar(50)) as
declare variable maxlen integer;
declare variable curpos integer;
declare variable ss1a char(1);
declare variable ss1b char(1);
declare variable ss2a char(1);
declare variable ss2b char(1);
begin
  Comparison = '';
  maxlen = character_length(ss1);
  if (maxlen  character_length(ss2)) then
maxlen = character_length(ss2);
  if (ss1 = ss2) then
comparison = 'Equal';
  if (comparison = '' and (ss1 starting ss2 or ss2 starting ss1)) then 
comparison = 'Substring';
  if (comparison = '') then
  begin
curpos = 1;
while (curpos = maxlen) do
begin
  ss1a = substring(ss1 from curpos   for 1);
  ss1b = substring(ss1 from curpos+1 for 1);
  ss2a = substring(ss2 from curpos   for 1);
  ss2b = substring(ss2 from curpos+1 for 1);
  if (ss1a is distinct from ss2a) then
  begin
if (comparison  '') then
  comparison = 'Differ more than one character';
if (comparison='') then
begin
  if (ss1a = ss2b and ss1b = ss2a) then
  begin
comparison = 'swapped';
curpos = curpos+1;
  end
  if (comparison='') then
comparison = 'One character differs';
end
  end
  curpos = curpos+1;
end
  end
  suspend;
end

I say strictly speaking, because whereas this would catch the difference 
between 'Hello' and 'Helol' or 'Hello' and 'Hel1o', it wouldn't catch 
additional or missing characters like 'Hello' vs 'Helo'. Should be fixable, but 
I'll leave that task for you (I'd expect you to need curpos1 and curpos2).

Having said all this, it wouldn't surprise me if there existed a UDF that did 
something similar to my execute block, I simply don't know since I've never 
needed one.

HTH,
Set

Re: [firebird-support] Firebird migration to increase perfomances

2015-06-23 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Yes I just checked my original query will return 6 rows without the distinct

OK, then lets add another CTE so that the calculations aren't multiplied:

with tmp1(surname, name, trxdate, source, job_number, creditnr, sourceid, 
serviceadvisOR) as
(select distinct trim(c.name||' '||c.surname), trim(ca.name), j.jdate, 
j.source, i.job_number, j.source2, j.sourceid, s.name||' '||s.surname
 from journal j
 join invoices i   on j.source = i.inv_nr
 left join customer c  on j.cid= c.cid
 left join cashcustomer ca on j.source = ca.invnr
  and i.job_number = ca.jobnr
 left join staff s on j.serviceadvisOR = s.staff_id
 where j.source not starting 'STOCK UNIT'
   and j.jdate between '2015/06/01' AND '2015/06/22'
   and j.source not starting 'DEPOSIT'
   and j.cid  0
   and j.module  2
   and ((j.source2 not starting 'S/D'
 and j.source2 not starting 'P/D')
 or j.source2 is null)
   and j.description not starting 'SPLIT INV'
   and j.jtype in (1, 4)),
tmp2(surname, name, trxdate, source, job_number, creditnr, sourceid, 
serviceadvisOR, credVAT, VAT,invoicetotalINC, credinc, creditnote,
 invoiceINCRedo, invoiceVATRedo, cost) as
(select t.surname, t.name, t.jdate, t.source, t.job_number, t.creditnr, 
t.sourceid, t.serviceadvisOR
sum(iif(j.accnr = '5995300' and j.module in (66, 77) and t.source2 = 
j.source2 and j.jtype = 1, coalesce(j.creditamount, 0) - 
coalesce(j.debitamount, 0), 0)),
sum(iif(j.accnr = '5995300' and j.jtype = 1, coalesce(j.creditamount, 
0) - coalesce(j.debitamount, 0), 0)),
sum(iif(j.accnr = '3993100' and j.jtype = 1, j.debitamount, 0)),
sum(iif(j.accnr = '1501500' and j.jtype = 1, coalesce(j.debitamount, 
0)-coalesce(j.creditamount, 0), 0)),
sum(iif(j.accnr = '1501500' and j.jtype = 4, coalesce(j.creditamount, 
0)-coalesce(j.debitamount, 0), 0)),
sum(iif(j.accnr = '3993100' and j.jtype = 1 and j.module = 77, 
j.creditamount, 0)),
sum(iif(j.accnr = '5995300' and j.jtype = 1 and j.module = 77, 
coalesce(j.debitamount, 0)-coalesce(j.creditamount, 0), 0)),
sum(iif(j.accnr starting '6' and j.jtype = 1, coalesce(j.debitamount, 
0)-coalesce(j.creditamount, 0), 0))
from tmp1 t
join journal j on t.source  = j.source
  and t.trxdate = j.jdate
  and j.jtype  in (1, 4)
  and (j.accnr in ('1501500', '3993100', '5995300')
or j.accnr starting '6')
group by 1, 2, 3, 4, 5, 6, 7, 8)
select surname, name, trxdate, source, job_number, creditnr, sourceid, 
serviceadvisOR, credVAT, VAT, invoicetotalINC, invoicetotalINC-VAT+credvat as 
invoicetotal,
   credinc+creditnote-invoiceINCRedo+invoiceVATRedo credits, 
invoicetotalINC-VAT+credinc+creditnote-invoiceINCRedo as nett, cost,
   invoicetotalINC-VAT+credinc+creditnote-cost-invoiceINCRedo as gp,
   
invoicetotalINC-VAT+credinc+creditnote-cost-invoiceINCRedo/NULLIF(invoicetotalINC-VAT+credinc+creditnote,
 0)*100 as gppersent
from tmp
where invoiceINC-invoicevat+credvat  0
order by 1,3,4

Does this get you the right result?

By the way, I'm positively surprised if the performance improved from almost 16 
seconds to 0.16 seconds, I'd hoped for up to a 10-fold improvement, not 
100-fold. I'm sure you didn't mean 0.16 milliseconds, Firebird is simply not 
that quick.

HTH,
Set

RE: [firebird-support] Firebird migration to increase perfomances

2015-06-23 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi Set

Wow your query runs like a bat out of hell J 0.16 Milliseconds !! and it
easier to maintain as you say.

The only issue is that it somehow multiplies the totals by 6 on all results
as compared mine?
 
i.e. mine will return an invoice total of say 18500.00 and yours will return
111000.00

This is across all the results any idea why?
 
Would you get six times as many rows in your result set with your original 
query if you didn't have the DISTINCT, Stef? Or  are any of the JOINs returning 
more than one row - e.g. are there six invoices for each entry in journal? This 
should be fairly simple to fix, but more information about the tables and how 
unique each JOIN are would be required.

Set



RE: [firebird-support] Firebird migration to increase perfomances

2015-06-22 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
At first glance, your plan seems OK. However, it would be better if we also 
could see the index definitions as well as get some information about index 
selectivity. And, this list removes attachments, so please post the text of the 
query as part of the message.

Set

Stef van der Merwe wrote:
I am not a SQL master but do know the basics.
I am have an issue with sub select queries and setting conditions.
Attached is the query I have a problem with,  see my comments on the last 
condition.

P.S see below is my plan I am sure the query could be done better for faster 
performance any advise would be greatly appreciated !!

Plan

PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX16))
PLAN (STAFF INDEX (STAFF_IDX1))
PLAN (CUSTOMER INDEX (CUSTOMER_IDX1))
PLAN (CA INDEX (CASHCUSTOMER_IDX2, CASHCUSTOMER_IDX1))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX16))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX16))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1))
PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1))
PLAN SORT (JOIN (J INDEX (JOURNAL_IDX1, JOURNAL_IDX2, JOURNAL_IDX2), I INDEX 
(INVOICES_IDX5)))

Adapted Plan

PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1)) PLAN (JOURNAL INDEX 
(JOURNAL_IDX6, JOURNAL_IDX1)) PLAN (JOURNAL INDEX (JOURNAL_IDX6, 
JOURNAL_IDX16)) PLAN (STAFF INDEX (STAFF_IDX1)) PLAN (CUSTOMER INDEX 
(CUSTOMER_IDX1)) PLAN (CA INDEX (CASHCUSTOMER_IDX2, CASHCUSTOMER_IDX1)) PLAN 
(JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1)) PLAN (JOURNAL INDEX (JOURNAL_IDX6, 
JOURNAL_IDX1)) PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1)) PLAN (JOURNAL 
INDEX (JOURNAL_IDX6, JOURNAL_IDX1)) PLAN (JOURNAL INDEX (JOURNAL_IDX6, 
JOURNAL_IDX16)) PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX16)) PLAN 
(JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1)) PLAN (JOURNAL INDEX (JOURNAL_IDX6, 
JOURNAL_IDX1)) PLAN (JOURNAL INDEX (JOURNAL_IDX6, JOURNAL_IDX1)) PLAN SORT 
(JOIN (J INDEX (JOURNAL_IDX1, JOURNAL_IDX2, JOURNAL_IDX2), I INDEX 
(INVOICES_IDX5)))

Prepare time = 16ms
Execute time = 15s 828ms
Avg fetch time = 465.53 ms
Current memory = 74 375 188
Max memory = 74 391 660
Memory buffers = 8 192
Reads from disk to cache = 253
Writes from cache to disk = 0
Fetches from cache = 730 569

[Non-text portions of this message have been removed]


RE: [firebird-support] Firebird migration to increase perfomances

2015-06-22 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi all,

 some years ago I developed a web application based on Interbase, Win98, PHP, 
 Apache. During those yeas has been lightly updated with lase
release of software, now the we application (10 users) use the follow:

Microsoft Server 2012 (64bit)
Apache 2.0
PHP 5.4
Firebird SQL 1.5 (3 databases, 250 Mbyte the bigger one)

The application works very well, but I'm asking to the mailing list if it 
possible to have more performance considering the database side without
make a big software refactoring. Which release do you suggest? What will be 
the percentage of performances get?

There can be lots of reasons for a database application being slow. If the 
database have huge tables, and the application is written thinking in terms of 
tables as opposed to datasets, then things will be slow regardless of Firebird 
version. If it is one particular query that is slow, you may be lucky with the 
optimizer working better on 2.5, but the correct way to fix things would still 
be to change the query. You may also experience the opposite when upgrading, 
i.e. that a query that works great on Fb 1.5, are slower on 2.5. And there are 
lots of other things that can make a database application slow.

Firebird 2.5 is generally better than Firebird 1.5, so a general advice would 
be to upgrade.  However, there’s no “performance factor” that was set to 5 in 
Fb 1.5 and 8 in Fb 2.5 and you’ve told us too little about your situation for 
us to give you any good advice. Some things will be quicker, some may be 
slower. ‘It works very well, how can I improve with minimum changes?’ is an 
almost impossible question to answer without more information regardless of 
whether you’re talking about databases, playing soccer or cooking.

Set


Re: [firebird-support] Firebird migration to increase perfomances

2015-06-22 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
 There can be lots of reasons for a database application being slow. If
 the database have huge tables, and the application is written thinking
 in terms of tables as opposed to datasets, then things will be slow

Svein.
An interesting comment, to me anyway, regarding tables vs datasets. I'm
no SQL guru, I just use Firebird as the backend of an app I'm writing,
but would you mind elaborating on what you've said. Just some
buzzwords/key words I should use on a google search would be greatly
appreciated.

Sure, Andrew, this is nothing complicated at all.

Once upon a time I used Paradox, a desktop database that I consider quite OK 
for small tables and single users. However, tables with one hundred thousand 
rows or so made things slow down considerably.

Using Firebird the Paradox way, i.e. loading all records and all fields every 
time is a bad idea except for tiny lookup tables. Firebird is good at finding 
the fields of the records you're interested in - including joining tables or 
doing some minor calculations upon the fields. Using Firebird simply as a place 
to store tables and doing all selection in code in your app rather than using a 
WHERE clause will make things slower - you may compare it to me prefering to 
take what I want to eat out of the fridge rather than take everything out of 
the fridge, find what I want to eat and put the rest back into the fridge. 
Similarly, I prefer to name the fields I need, rather than use SELECT * (there 
are exceptions, of course).

Generally speaking, a result set should only contain the data that you require 
for whatever you're doing, and the smaller the result set is, the better.

Using Firebird the client/server way with appropriate indexing, it doesn't 
normally matter all too much how big tables and databases are, although I must 
admit that I'm only used to working with tables with a few million rows, and 
have no experience with really big databases.

Set

RE: [firebird-support] Firebird 2.52 gbak fails to do a restore - error trigger (3)

2015-06-12 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Unlike Vlad, Helen and Thomas, I know next to nothing about problems like yours 
(I'm good at SELECTs, which is way different from corrupted backups). Hence, 
listen more to them than to me.

gbak:restoring privilege for user SYSDBA
gbak: ERROR:action cancelled by trigger (3) to preserve data integrity
gbak: ERROR:table/procedure has non-SQL security class defined
gbak:Exiting before completion due to errors

I read this as attempting to grant SYSDBA something that is impossible. E.g. it 
wouldn't surprise me if InterBase 6 allowed you to grant EXECUTE to a table 
(EXECUTE only makes sense to grant to a procedure), and that Firebird barks 
since is stricter regarding syntax than IB 6 was. 

Now, I don't know how to restore a database without grants specified to the 
table (others may know), but I'd recommend you to try restoring using the -o 
switch (one table at a time), possibly also using the -i (set indexes inactive) 
and -n (check constraints disabled) switches.

But as I said, this is rambling and guesswork, as opposed to Vlad's, Helen's 
and Thomas' knowhow.

Set

PS! Firebird 2.5 is a considerably better database than InterBase 6.0 was 
(although 2.5.1 had a flaw that almost required backup/restore when upgrading 
to 2.5.2 or higher)


[firebird-support] GROUP BY optional with constants?

2015-06-10 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I did a mistake with a query I wrote (Fb 2.5.3 or 2.5.4), but to my surprise 
Firebird did not complain and gave me the desired result. What I found was that 
whilst Firebird complains about missing GROUP BY if writing something like

SELECT 'This does not work', RDB$RELATION_ID, list(RDB$CHARACTER_SET_NAME)
FROM RDB$DATABASE

It does not complain if constants are used:

SELECT 'This works', list(RDB$CHARACTER_SET_NAME)
FROM RDB$DATABASE

or even

SELECT 'This works', RDB$RELATION_ID,  list(RDB$CHARACTER_SET_NAME)
FROM RDB$DATABASE
GROUP BY 2

Now, I do not object to not having to write GROUP BY - I'm just very surprised 
that it seems to be optional with constants. Is there any particular reason, or 
is this a 'bug to be appreciated rather than fixed'?
Set


RE: [firebird-support] Re: Inssuficient rights for operation....

2015-06-09 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hello. I used Firebird 1.5.6 on server on WIN7, a database with a role with 
full rights, and a user defined in ROLE, USER.
I have a problem. In the network with a application, on different client 
station, login with the USER, all functions work OK.
From server or another WIN7 station, with USER login, a have one error, with 
insufficient sql rights for operation, no permission to read/select acces to 
TABLE. 
All different functions work OK. ROLE with GRANTS in all tables.
The solution from win7 is to give rights on USER for table CONFIG_BALANTA, the 
rights from the ROLE give this error
WHY THE DIFFERENT functionality? Same user, same rights on database. 

You may well know all I'm writing here, just thought I should point it out if 
it happened to be a simple misunderstanding.

It does not matter from where you log in. What does matter, is username 
(obviously) and that you connect using the correct role. Let's say I'm a member 
of two separate roles: DB_READ and DB_WRITE which have the obvious rights to a 
table that I have no access to myself. If I connect to the database specifying 
DB_WRITE as the role, I can do whatever I want, if I use DB_READ when 
connecting, then I can read, but not write data and if I do not specify any 
role when connecting, then I cannot do anything (not even read) unless rights 
have been granted me as a user rather than any role I'm a member of.

HTH,
Set


RE: [firebird-support] How to CAST float to integer with error?

2015-05-26 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hello,
is it possible by using CAST or in any other way to get database error when 
casting such number to integer?
SELECT CAST('13.245' AS INTEGER) FROM RDB$DATABASE
This gives 13 but instead I would like to get an error because precision is 
lost.

However, I would like to NOT get an error when doing this:
SELECT CAST('13.000' AS INTEGER) FROM RDB$DATABASE
Becasue here precision is not lost.

Is it possible to obtain such behaviour in easy way or do I have to use 
regular expressions?

Not quite what you're asking for, Bruce, but 

SELECT CAST(13.245 AS INTEGER) FROM RDB$DATABASE
WHERE CAST(13.245 AS INTEGER) * 1000 = cast(13.245 * 1000 as Integer)

does return any rows, whereas this statement does:

SELECT CAST(13.000 AS INTEGER) FROM RDB$DATABASE
WHERE CAST(13.000 AS INTEGER) * 1000 = cast(13.000 * 1000 as Integer)

HTH,
Set


RE: [firebird-support] Parametrized queries and execute statement - dynamic parameter list

2015-05-26 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
3. when i change proc to use execute statement with parameters
 
SET TERM ^ ;
CREATE PROCEDURE MY_PROC_CALC_EXEC_PARAM(ID INTEGER) RETURNS(SUM_AAA INTEGER)
AS
DECLARE VARIABLE VAR_SQL VARCHAR(1000);
BEGIN
  VAR_SQL = 'SELECT SUM(AAA) FROM TABLEY WHERE ID=:ID';
  EXECUTE STATEMENT (VAR_SQL) (ID := :ID) INTO :SUM_AAA;
  SUSPEND;
END^
SET TERM ; ^
 
and run query
SELECT (SELECT P.SUM_AAA FROM MY_PROC_CALC_EXEC_PARAM(T.FIELD_ID) P) FROM 
TABLEX T
 
than select is prepared only once - ok :)

I'm impressed if Firebird understands that VAR_SQL doesn't change between each 
iteration so that preparing once is possible!

4. but how to change this sample code to use paramaters and do not prepare 
statement on every record?
 
SET TERM ^ ;
CREATE PROCEDURE MY_PROC_CALC_EXEC_PARAM(ID INTEGER) RETURNS(SUM_AAA INTEGER)
AS
DECLARE VARIABLE VAR_SQL VARCHAR(1000);
DECLARE VARIABLE VAR_BBB INTEGER;
DECLARE VARIABLE VAR_NR INTEGER;
BEGIN
  VAR_SQL = 'SELECT SUM(AAA) FROM TABLEY WHERE ID=:ID ';
  VAR_NR = 1;
  FOR SELECT 
  BBB 
  FROM 
  TABLEZ 
  WHERE ID=:ID
  INTO :VAR_BBB
  DO
    BEGIN  
   /* DO SOME CALCULATION ON VAR_BBB */
   
   VAR_SQL = VAR_SQL || ' OR ID=:ID' || VAR_NR; 
        How to add here parameter to list of parameters for below execute 
statement?
    END
 
  EXECUTE STATEMENT (VAR_SQL) (ID := :ID,  ID1, ID2, ID3 ...) - How to 
specify parameters dynamically?
  INTO :SUM_AAA;
  
  SUSPEND;
END^
SET TERM ; ^
 
 
Is this somehow possible? Or should i add this to the Firebird bug tracker as 
new feature request?
This is important from performance point of view.
 
Here you change the SQL for each iteration, hence I cannot see how it would be 
possible to prepare only once. What you could try, is to use a temporary table, 
change your statement to:

SELECT SUM(Y.AAA) FROM TABLEY Y
JOIN TMP_TABLE T ON Y.ID = T.ID

and in your loop do

INSERT INTO TMP_TABLE(ID) VALUES(:VAR_NR)

HTH,
Set


Re: [firebird-support] Why index is not used in this query?

2015-05-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
SELECT * FROM
TABLE_2 T2
  INNER JOIN
TABLE_1 T1
  ON
 T2.TABLE_1_ID = T1.ID

After executing this query I am getting such plan:

PLAN JOIN (T1 NATURAL, T2 INDEX (FK_TABLE_2))

Why in case of TABLE_1 optimizer did not chose index PK_TABLE_1? And why I am 
getting error when i try to enforce it with:
PLAN JOIN (T1 INDEX (PK_TABLE_1), T2 INDEX (FK_TABLE_2))

Admittedly, my way of plan thinking is far from the way things are 
implemented, but still - it normally helps me understand why the optimizer 
behaves as it does.

A simple query like yours I typically consider from the first table to the last 
in the plan. Hence, I'd start with T1.

SELECT *
FROM TABLE_1 T1

Here, there's no limiting JOIN, WHERE or anything similar that can be used to 
limit the number of rows to return (T2 isn't involved yet, hence any clause 
referring to that tuple cannot be considered). So, the quickest and only 
sensible option (at least unless you want to slow things down) is to go NATURAL 
on T1.

Then, we add T2

INNER JOIN TABLE_2 T2 ON T2.TABLE_1_ID = T1.ID

Here, you already have T1 available, and using an index for T2.TABLE_1_ID will 
help reducing the potential number of records to look up considerably.

Is there no way to utilize the index for T1.ID? Sure there is, you can start 
with T2 rather than T1. However, then you would start with

SELECT * FROM
TABLE_2 T2

which cannot use an index.

Adding

INNER JOIN TABLE_1 T1 ON T2.TABLE_1_ID = T1.ID

would, however, benefit from using the index for T1.ID.

Is there really no way to use an index for both fields? No, not unless you add 
a WHERE (or ON) clause that limits the result set through including one or more 
constants, e.g.

AND T1.ID between 2 and 4

Having said that, it is only on rather big tables that it is bad to see NATURAL 
on the first tuple in the plan (well, in more complex queries - e.g. involving 
subselects - it may not be the first tuple). And I think you would normally use 
a proper WHERE clause on big tables, although it is of course thinkable to e.g. 
want to have a query that should find all persons being a citizen of both 
London and Paris (millions of persons in both tables, but only a very small 
subset being part of both). Such rare queries are normally slowish, sometimes 
even after optimization.

HTH,
Set

Re: [firebird-support] Re: Invalid expression in the select list (not contained in either an aggregate function or the GROUP BY clause)

2015-05-07 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Except that grouping by OPS_ZIP would not accomplish the same thing. Multiple 
zip codes map to the same REGION_ID and the zip codes might not be contiguous.

Guess I'm going to have to rethink this.

What about

with tmp(PB_LOAD_TYPE, APPT_DATE, REGION_ID, PICKUP, DELIVERY) as
(SELECT PB_LOAD_TYPE, 
   CAST(COALESCE(OPS_ONBOARD_TIME, OPS_DELIVERED_TIME, OPS_APPT_LOW, 
'TODAY') AS DATE),
   COALESCE((SELECT FIRST 1 CTRR_REGION_ID
   FROM CT_REGION_RANGES
   WHERE OPS_ZIP BETWEEN CTRR_LOW_ZIP AND CTRR_HIGH_ZIP
   ORDER BY CTRR_REGION_ID), 'N/A'),
   IIF(OPS_TYPE = 'P', 1, 0),
   IIF(OPS_TYPE = 'P', 0, 1)
  FROM OPS_STOP_REC
LEFT JOIN OPS_HEADER ON PB_ID = OPS_ORDER_ID
  WHERE PB_TYPE = 'O' AND
PB_DT_ENT = :PB_DT_ENT)

SELECT PB_LOAD_TYPE, APPT_DATE, REGION_ID, sum(PICKUP) as PICKUPS, 
sum(DELIVERY) as DELIVERIES
  FROM tmp
  GROUP BY PB_LOAD_TYPE, APPT_DATE, REGION_ID
  ORDER BY APPT_DATE, PB_LOAD_TYPE, REGION_ID

HTH,
Set

Re: [firebird-support] Is it possible to do this with window function?

2015-05-02 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi guys.

Hi Bruce!

I am having such data:

ID   DATE_TIMETYPE
101.01.2015, 00:00:00.000A
201.01.2015, 00:01:00.000A
301.01.2015, 00:02:00.000A
401.01.2015, 00:10:00.000B
501.01.2015, 00:15:00.000B
601.01.2015, 00:20:00.000A
701.01.2015, 00:25:00.000A

Is it possible to write query which will result:

TYPE  DATE_MIN   DATE_MAX
A01.01.2015, 00:00:00. 000  01.01.2015, 00:02:00.000

B01.01.2015, 00:10:00.000  01.01.2015, 00:15:00.000

A01.01.2015, 00:20:00.000  01.01.2015, 00:25:00.000

As you can see I would like to have three groups and not two like it would 
have been with usage of standard GROUP BY. I know I can write a selectable 
stored procedure which will result me such data but is it possible to do with 
new window functions and partitioning?

Thanks.

Well, that's a rather unusual enquiry, but your particular question can be 
solved by rather standard SQL (probably even worked on InterBase before 
Firebird was born).

SELECT A.TYPE, A.DATE_TIME as DATE_MIN, B.DATE_TIME as DATE_MAX
FROM MyTable A
JOIN MyTable B 
  ON A.TYPE = B.TYPE
 AND B.ID = A.ID
LEFT JOIN MyTable ANot ON A.ID-1 = ANot.ID AND A.TYPE = ANot.TYPE
LEFT JOIN MyTable NotBetween ON NotBetween.ID BETWEEN A.ID AND B.ID AND 
A.TYPE IS DISTINCT FROM NotBetween.TYPE
LEFT JOIN MyTable BNot ON B.ID+1 = BNot.ID AND B.TYPE = BNot.TYPE
WHERE ANot.ID IS NULL
  AND NotBetween.ID IS NULL
  AND BNot.ID IS NULL

If there can be holes in the sequence - e.g. if the last record had ID 8 rather 
than 7 and you wanted it grouped with ID 6 even though there were no ID 7, 
things would still be feasible, but somewhat more complex.

Sorry for not using Windows functions - I'm still on Fb 2.5 and don't have them 
under my hood yet.

Set

SV: [firebird-support] SQL Case query takes 4 minutes 30 seconds to execute !!

2015-04-29 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
[I've removed irrelevant details from your original question]

I sincerely hope I am in the right place. We have a query which takes 4 
minutes 30 seconds to execute this is simply
too long. Please help !

Definitely, Stef, most performance problems can be solved on this list, and I 
agree that 4 and a half minute sounds long.

CREATE TABLE JOURNAL (
JDATE   DATE,
SOURCE2 VARCHAR(40),
ACCNR   INTEGER,
SUPPID  INTEGER,
JTYPE   INTEGER);

CREATE INDEX JOURNAL_IDX1 ON JOURNAL (JDATE);
CREATE INDEX JOURNAL_IDX13 ON JOURNAL (SUPPID);
CREATE INDEX JOURNAL_IDX16 ON JOURNAL (SOURCE2);
CREATE INDEX JOURNAL_IDX2 ON JOURNAL (JTYPE);
CREATE INDEX JOURNAL_IDX3 ON JOURNAL (ACCNR);

There are only 350,000 (350 Thousand)records in the table

Below is my actual sql query

select distinct
sum((case (extract (year from jdate )||''||extract ( month from jdate ))
when 20154 then (coalesce(invoicetotal,0)-coalesce(paid,0)) else 0 end))  as 
Current_days,
sum((coalesce(invoicetotal,0)-coalesce(paid,0)))as totaldue
 from (select (jdate)as jdate,
(Select COALESCE(sum(debitamount),0 )
 from journal where accnr = '5995100'  and suppid=j.suppid and 
 source2 = j.source2 and jdate = j.jdate)as paid,
(Select COALESCE(sum(creditamount),0 )
 from journal where accnr = '5995100'  and suppid=j.suppid and source2 
 = j.source2  and jdate = j.jdate)as invoicetotal
   from journal j
where j.jdate = '2015/04/28'
and j.accnr = 5995100
and j.SUPPID = '1'
and (j.jtype = 2 or j.jtype = 99))
having sum((invoicetotal-paid))0
order by  2 asc

Please let me know if I should provide more information.

The generated plan could have given more hints as to what is wrong, but I've 
tried to rewrite your query anyway. So, could you see if the following query 
gets the same result and whether or not it is any quicker?

with DateSource(jdate, source2) as
(select distinct jdate, source2
 from journal
 where jdate = '2015/04/28'
   and accnr = 5995100
   and SUPPID = 1
   and jtype in (2, 99)),
tmp(jdate, paid, invoicetotal) as
(select d.jdate, sum(debitamount), sum(creditamount)
 from journal j
 join DateSource d on j.jdate = d.jdate and j.source2 = d.source2
 where j.accnr = 5995100
   and j.SUPPID = 1
 group by 1)

select sum(iif(jdate between '2015/04/01' and '2015/04/30', invoicetotal - 
paid, 0) current_days,
   sum(invoicetotal - paid) totaldue
from tmp
having sum(invoicetotal - paid)  0
order by 2

It would be interesting to learn whether or not this query is any quicker, and 
if it isn't, the plans of both your original query and my modified version. 
Please also check whether the  modified query gets the correct result, there 
may be subleties that I missed.

HTH,
Set

RE: [firebird-support] SQLAnywhere to Firebird possibility

2015-04-24 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi,

I have been a major contributor to Firebird since 2003, also my previous 
company BASX, which I was the Head developer of, 
was a gold sponsor of Firebird.

I have recently moved to another company that uses SQLAnywhere.

They are interested in moving to Firebird.

But Firebird does not have some of the key features of SQL Anywhere, they 
depend on a lot.

like XMLForest, XMLElement, etc, full XML compatibility is available in 
both SQLAnywhere and Oracle.

like local temporary tables/ Hash Tables.

like enabled select column aliases to be reused in same SQL.

eg.

SELECT (x/y) AS MYDIV
,MYDIV * Z AS MYDIVMULTIPLIED
FROM RDB$DATABASE.

Is it possible. If I put an option on the table, that the company I work for 
sponsors Firebird. and then Firebird could add this type of stuff?

Your particular example I would typically write (using Fb 2.5, but I think it 
has been available since 2.0 or 2.1):

With tmp(MYDIV) as
(SELECT (x/y) from RDB$DATABASE)
SELECT MYDIV, MYDIV * Z AS MYDIVMULTIPLIED
FROM tmp

The answer to your more important question about sponsorship, I would guess 
depends on the individual feature and how it fits with the general ideas of the 
Firebird future. Certainly sponsors can influence priorities in development. 
The developers sometimes lurk on this list, but I think firebird-devel could be 
a more proper place to discuss sponsorship since there are more of them there 
and it could be easier to see how the desires of your company fits the 
development.

Set


RE: [firebird-support] Need Speed Optimization for SQL

2015-04-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I have below SQL and DDL of respective columns used in this SQL.

Below sql takes 6-7 seconds to give the result.

Would it be possible to bring the output time to 1 seconds, coz there are some 
other operartion I need to perform based on this sql output withing short 
period of t ime.

SQL:

SELECT
  Sum(CRM_DOCUMENT_ITEMS.QUANTITY) AS Delivered,
  CRM_DOCUMENT_ITEMS.FK_JOB_ITEM
FROM
  CRM_DOCUMENT_ITEMS
  INNER JOIN CRM_DOCUMENT_HEADER ON CRM_DOCUMENT_ITEMS.FK_DOCUMENT_HEADER = 
 CRM_DOCUMENT_HEADER.PK_DOCUMENT_HEADER
WHERE
  CRM_DOCUMENT_HEADER.DOCUMENT_TYPE = 1 and CRM_DOCUMENT_ITEMS.FK_JOB_ITEM in 
 (select PK_JOB_ITEMS from CRM_JOB_ITEMS where FK_JOB = 
 '{8BDDED49-8509-48C1-A169-B7E68A74C230}')
GROUP BY
  CRM_DOCUMENT_ITEMS.FK_JOB_ITEM

Hopefully, Rob or Virgos solutions worked, if not try this:

with TMP(PK_JOB_ITEMS) as
(select distinct PK_JOB_ITEMS
 from CRM_JOB_ITEMS where FK_JOB = '{8BDDED49-8509-48C1-A169-B7E68A74C230}')
select
  Sum(cdi.QUANTITY) AS Delivered,
  cdi.FK_JOB_ITEM
from tmp t
join CRM_DOCUMENT_ITEMS cdi on t.PK_JOB_ITEMS = cdi.FK_JOB_ITEM
join CRM_DOCUMENT_HEADER cdh ON cdi.FK_DOCUMENT_HEADER = cdh.PK_DOCUMENT_HEADER
where cdh.DOCUMENT_TYPE = 1

HTH,
Set


RE: [firebird-support] Need Speed Optimization for SQL

2015-04-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi SET,

Nice to see you here, but I am getting below error after executing your sql, i 
think group by clause is needed, would you please help?

Yes, sorry I forgot group by:

with TMP(PK_JOB_ITEMS) as
(select distinct PK_JOB_ITEMS
from CRM_JOB_ITEMS where FK_JOB = '{8BDDED49-8509-48C1-A169-B7E68A74C230}')
select
Sum(cdi.QUANTITY) AS Delivered,
cdi.FK_JOB_ITEM
from tmp t
join CRM_DOCUMENT_ITEMS cdi on t.PK_JOB_ITEMS = cdi.FK_JOB_ITEM
join CRM_DOCUMENT_HEADER cdh ON cdi.FK_DOCUMENT_HEADER = cdh.PK_DOCUMENT_HEADER
where cdh.DOCUMENT_TYPE = 1
group by cdi.FK_JOB_ITEM

HTH,
Set


RE: [firebird-support] Need Speed Optimization for SQL

2015-04-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi SET,

I tried as below way by adding Group By clause:

with TMP(PK_JOB_ITEMS) as
(select distinct PK_JOB_ITEMS
from CRM_JOB_ITEMS where FK_JOB = '{8BDDED49-8509-48C1-A169-B7E68A74C230}')

select
Sum(cdi.QUANTITY) AS Delivered,
cdi.FK_JOB_ITEM
from tmp t
join CRM_DOCUMENT_ITEMS cdi on t.PK_JOB_ITEMS = cdi.FK_JOB_ITEM
join CRM_DOCUMENT_HEADER cdh ON cdi.FK_DOCUMENT_HEADER = cdh.PK_DOCUMENT_HEADER
where cdh.DOCUMENT_TYPE = 1
group by cdi.FK_JOB_ITEM

And sql is taking 1.893 seconds

Any other way to make this more faster ? Please If possible

If you have indexes (or if they are keys) for these three fields:

CRM_JOB_ITEMS.FK_JOB
CRM_DOCUMENT_ITEMS.FK_JOB_ITEM
CRM_DOCUMENT_HEADER.PK_DOCUMENT_HEADER

then it will most likely be difficult to optimize this query any further 
(sometimes having trigger generated summary tables can help, but that does 
complicate things quite a bit and I've never seen it done when several tables 
are involved, so I'd only consider this if this particular query was executed 
frequently and was one of the most important queries in your system).

Note that while I may be considered a Firebird SELECT expert, I am a novice 
regarding other parts of Firebird (like configuration settings), so maybe 
someone else can help you speed up your query a bit more.

Set


[firebird-support] Re: Need Speed Optimization for SQL

2015-04-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
CRM_DOCUMENT_HEADER Table - PK_DOCUMENT_HEADER is primary key and having 
seperate index on this column as well

What do you mean by this, Vishal?

I think it was fixed a while ago, but duplicate indexes used to confuse the 
optimizer, so PK_DOCUMENT_HEADER ought not to be both the primary key and have 
a separate single-field index (unless the PK or index is DESCENDING or consists 
of more than one field) - at best it makes INSERTs marginally slower due to 
having to maintain two identical indexes.

Set


Re: [firebird-support] SQL puzzle: Order based on Prerequisite

2015-04-12 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
In a table called Steps, I have the following fields:

ID, B4Me, Dsc,

-ID field contains a unique ID for each record
-B4Me contains the ID of some other record in the table that MUST appear in a 
result set, BEFORE this record. B4Me may be null. This is called the B4Me 
order.
-Records will be entered in random order, so Natural order cannot be relied 
upon as a substitute for B4Me

I need an SQL statement that will return all records with a user supplied 
search word (such as oil, or glycol or micron) in the Dsc field, which 
could return 
a variable number of records, but what ever the number of records returned, 
the *order* must be such that each record is preceded by the record who's ID 
matches the B4Me value of a given record.nbs p;

Important Notes:

- The SQL may return one or more records with a blank B4Me. In which case, 
Natural order can be used for those records, and they are all considered 
First or 
rather, Before everything else.  Once all the records with a blank B4Me are 
listed, the remaining must be in the B4Me order.

- It is possible, though unlikely, that following the B4Me order will result 
in a circular reference. (Two or more records that reference each other, or 
the last 
record in a large result set, references the first (or any other in the result 
set) record in the B4Me field).  In these cases, the SQL must either list all 
records until 
a circular reference is detected, then don't list the offending record, or 
display an error message, but it must not hang FB and get an out of memory 
error.

Thanks in advance for any help you can provide.

The possibility of a circular reference, makes this a difficult task. SQL is 
great for working with sets of data, iteration and recursion are more 
difficult, but doable with CTEs or stored procedures, but I cannot think of how 
to exit a circular reference gracefully within one statement.

Hence, I'd recommend using a global temporary table:

CREATE GLOBAL TEMPORARY TABLE MyTmp
(ID INTEGER, OrderNo INTEGER)
ON COMMIT DELETE ROWS; --doesn't really matter whether you commit or delete 
rows in this particular case...

and then EXECUTE BLOCK or a STORED PROCEDURE;

EXECUTE BLOCK(MySearch varchar(50) = :MySearch) Returns(OutID Integer) as
  declare variable ID integer;
  declare variable ID2 integer;
  declare variable OrderNo integer;
begin
  delete from MyTmp; --start afresh every time you execute this block
  OrderNo = 1000;
  for select ID, B4Me
  from Steps
  where Dsc containing :MySearch
  into :ID, :ID2 do
  begin
while (:ID is not null) do
begin
  if exists(select * from MyTmp where ID = :ID) then
  begin  --This is how to escape from a circular reference
id = null;
  end
  else
  begin
INSERT INTO MyTmp(ID, OrderNo)
VALUES(:ID, :OrderNo);
OrderNo = OrderNo - 1;
ID = ID2;
if (ID is not null) then
begin
  SELECT B4Me from Steps where ID = :ID into :ID2;
end
  end
end
  end
  for select ID from MyTmp order by OrderNo into :OutID do
suspend;
end

I've interpreted Before everything else to mean before any of its own 
children, not before any children regardless of heritage - or, to put it 
simple - you would appear before all your children, but not necessarily before 
my children.

Hopefully, this can serve as a template for how you can solve your situation, 
despite being more than one statement.
Set

RE: [firebird-support] Recursive CTE question

2015-04-08 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Can the question be rephrased as you being interested in which sets are 
identical, Elias? If I understand things correctly, 
I would assume double negation to be the simple answer you're looking for:

with tmp(id) as
(select distinct id from CRITICALPARAMVALS)

select t.id, t2.id
from tmp t
join tmp t2 on t.id  t2.id
where not exists(select * from CRITICALPARAMVALS a 
 where t.id = a.id
   and not exists(select * from CRITICALPARAMVALS b
  where t2.id = b.id
and a.PARAM=b.param and (exists (select 
 isequal from TEST_FLOAT_EQ(a.val, b.val, 1e-5) where ISEQUAL=1

Sorry, the above select returns equal sets, but also sets where B is a superset 
of A. You need to add

and not exists(select * from CRITICALPARAMVALS a 
 where t2.id = a.id
   and not exists(select * from CRITICALPARAMVALS b
  where t.id = b.id
and a.PARAM=b.param and (exists (select * 
from TEST_FLOAT_EQ(a.val, b.val, 1e-5) where ISEQUAL=1

for it to only find identical sets.

Needless to say, such a query can be a bit slow with huge tables. Moreover, I 
don't know how TEST_FLOAT_EQ is implemented or why you use this rather than

a.val BETWEEN b.val - 0.1 and b.val + 0.1

HTH,
Set


RE: [firebird-support] V1.56 query killing my V2.54 app

2015-04-08 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Ok, used the +0 and worked.

On v1.56 I was used with setting up a high granularity data column (col04Int - 
part of the primary key) with a True/false (0/1) type of column 
(ColDetSmIntFlag) to boost the selectivity of the index
IXColDetSmIntFlag. I kept the index with that configuration for a just in 
case. (The stat of the index is 0,01407...)

Set, don't get me wrong, I am very gratefull for your help and for Firebird, 
but saying that a Natural on a big table seems better than an index doesn't 
compute for me, and I've been using Firebird
since Interbase and Oracle since v6 (as DBA BTW). At a least case scenario it 
should use the PK when there is a declared join using the PK. For me, the new 
optimizer is wierd and highly illogical.

Glad to hear that +0 worked.

We used Fb 1.5 for a long time (switched from 1.5 to 2.5 a year or two ago) and 
I’m happy to say that my impression generally is that the optimizer in 2.5 is 
better than it was in 1.5 and that the need for tricks like +0 is less than it 
used to be. Though there will of course be differences, and it is not a 
surprise that you notice some drawbacks rather than benefits when upgrading a 
particular database (I assume you have optimized poorly performing queries with 
Fb 1.5 long ago, rather than been waiting for the upgrade). If you compare new, 
unoptimized queries between 1.5 and 2.5, odds are that you would conclude that 
2.5 are better.

I guess the reason for the optimizer preferring the NATURAL plan is a 
combination of msttbl having about half the number of records of dettbl and the 
index on ColDetSmIntFlag having lousy selectivity (the optimizer doesn’t have 
histograms yet (I am uncertain whether histograms are part of Firebird 3 or if 
it will be a later release), and doesn’t know that 1 is a less frequent value 
than 0).

Set


Re: [firebird-support] V1.56 query killing my V2.54 app

2015-04-07 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi all,

I'm trying to upgrade an app to v2.54 from v1.56 but there are some queries 
that aren't planning the way they should.

I have this query:

Select Distinct a.col01Int, a.col02SmInt, a.col03SmInt, a.col04VarCh45
from  dettbl b
   Inner Join msttbl a on (a.col01Int = i.col01Int and
   a.col02SmInt = i.col02SmInt and
   a.col03SmInt = i.col03SmInt)
where
   b.ColDetSmIntFlag = 1
Order by a.col04VarCh45

on v1.56 I get this plan:
PLAN SORT (SORT (JOIN (B INDEX (IXColDetSmIntFlag),A INDEX (PK_msttbl

and on v2.54 I get
PLAN SORT (SORT (JOIN (A NATURAL, B INDEX (FK_dettbl

that is killing my app. The tables in question have 450K+ and 800K+ rows.

ALTER TABLE msttbl ADD CONSTRAINT PK_msttbl PRIMARY KEY (col01Int, col02Int, 
col03Int);
CREATE INDEX IXmsttbl_col04VarCh45 ON msttbl (col04VarCh45);
ALTER TABLE dettbl ADD CONSTRAINT PK_dettbl PRIMARY KEY col01Int, col02Int, 
col03Int, col04Int);
ALTER TABLE dettbl ADD CONSTRAINT FK_dettbl FOREIGN KEY (col01Int, col02Int, 
col03Int) REFERENCES msttbl (col01Int, col02Int, col03Int);
CREATE INDEX IXColDetSmIntFlag ON dettbl (ColDetSmIntFlag, col04Int);

I've been changing the query and trying to change indexes to no success.
Is there a way to force FB 2.54 to chose the right indexes?

Hi Andrew!

Forcing a correct plan is not always benefitial or possible, but it is normally 
quite easy to prevent a bad plan from being used. I'd recommend you to try:

Select Distinct a.col01Int, a.col02SmInt, a.col03SmInt, a.col04VarCh45
from  dettbl b
   Inner Join msttbl a on (a.col01Int = b.col01Int+0 and
   a.col02SmInt = b.col02SmInt and
   a.col03SmInt = b.col03SmInt)
where
   b.ColDetSmIntFlag = 1
Order by a.col04VarCh45

The additional +0 should prevent FK_dettbl from being used, but there's no 
guarantee that another poor plan cannot be chosen, so this kind of modification 
sometimes needs a couple of attempts before you reach a good result.

HTH,
Set

Re: [firebird-support] Recursive CTE question

2015-04-07 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi everyone!

This might not be a straightforward Firebird question, but I'm hoping there's 
a feature I'm unaware of that can help me beyond plain-vanilla SQL.

I have two tables.  The first is a list of names of critical parameters, and 
the second relates certain object IDs, critical parameter names, and critical 
parameter values:

[removed CRITICALPARAMS definition since I don't think it is of importance to 
the question]

CREATE TABLE CRITICALPARAMVALS
(
ID INTEGER NOT NULL,
PARAM Varchar(32) NOT NULL,
VAL Float NOT NULL,
CONSTRAINT PK_CRITICALPARAMVALS_1 PRIMARY KEY (DATAPOINTHASH,PARAM)
);

insert into CRITICALPARAMVALS values (1, 'a', 0.0);
insert into CRITICALPARAMVALS values (1, 'b', 0.0);
insert into CRITICALPARAMVALS values (1, 'c', 2.0);
insert into CRITICALPARAMVALS values (1, 'foo', 99.0);
insert into CRITICALPARAMVALS values (2, 'a', 0.0);
insert into CRITICALPARAMVALS values (2, 'b', 0.0);
insert into CRITICALPARAMVALS values (2, 'c', 2.0);
insert into CRITICALPARAMVALS values (2, 'foo', 99.0);
insert into CRITICALPARAMVALS values (3, 'a', 0.0);
insert into CRITICALPARAMVALS values (3, 'b', 0.0);
insert into CRITICALPARAMVALS values (3, 'c', 1.0);
insert into CRITICALPARAMVALS values (3, 'foo', 98.0);
insert into CRITICALPARAMVALS values (4, 'a', 0.0);
insert into CRITICALPARAMVALS values (4, 'b', 0.0);
insert into CRITICALPARAMVALS values (4, 'c', 1.0);
insert into CRITICALPARAMVALS values (4, 'foo', 98.0);
insert into CRITICALPARAMVALS values (5, 'a', 0.0);
insert into CRITICALPARAMVALS values (5, 'b', 0.0);
insert into CRITICALPARAMVALS values (5, 'c', 2.0);
insert into CRITICALPARAMVALS values (5, 'foo', 98.0);

The problem is to partition the critical parameter space, grouping together 
all object IDs that have the same parameter values.  
We can think of using a seed object ID, and asking what other IDs belong to 
the same partition as the seed object.

In our example, objects 1 and 2 form a partition, 3 and 4 form another, and 5 
forms a third.  
All five objects are equal in the critical parameters a and b, but differ in 
parameters c and foo.

Is there any way to solve this using plain-vanilla SQL?  How about a recursive 
CTE?

Can the question be rephrased as you being interested in which sets are 
identical, Elias? If I understand things correctly, I would assume double 
negation to be the simple answer you're looking for:

with tmp(id) as
(select distinct id from CRITICALPARAMVALS)

select t.id, t2.id
from tmp t
join tmp t2 on t.id  t2.id
where not exists(select * from CRITICALPARAMVALS a 
 where t.id = a.id
   and not exists(select * from CRITICALPARAMVALS b
  where t2.id = b.id
and a.PARAM=b.param and (exists (select 
isequal from TEST_FLOAT_EQ(a.val, b.val, 1e-5) where ISEQUAL=1

At least, I guess (haven't tested anything, just know that double negation 
has been an answer to set equality before) this query would return two rows 
like this:

1 2
3 4

HTH,
Set

Re: [firebird-support] V1.56 query killing my V2.54 app

2015-04-07 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Actually, the problem isn't with FK_dettbl, but with the A Natural. In a 
Master detail relationship with 450K+ rows in the master and 800K+ rows in the 
detail, that natural is a killer.

The problem is that Firebird thinks that

PLAN SORT (SORT (JOIN (A NATURAL, B INDEX (FK_dettbl

is a better choice than 

PLAN SORT (SORT (JOIN (B INDEX (IXColDetSmIntFlag),A INDEX (PK_msttbl

The optimizer doesn't think NATURAL is better than using an index, it thinks 
that the selectivity of FK_dettbl is so much better than IXColDetSmIntFlag and 
PK_msttbl combined that it outweights the cost of going NATURAL on A.

Normally, it isn't all too bad to go natural on the first table of a plan, but 
b.ColDetSmIntFlag = 1 may be more selective than the optimizer thinks and then 
preventing a particular plan from being used  can help speed up queries like 
yours. The +0 should prevent FK_dettbl from being used, and I'm pretty sure the 
optimizer will not try to go natural on both tables. Hence the optimizer should 
suggest another plan - hopefully the one you want.

HTH,
Set



RE: [firebird-support] Cast as Numeric without parenthesis

2015-03-26 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I would expect numbers in the range -2147483648 to +2147483647 to be accepted 
(the size of an integer), and then there’s a separate field for storing whether 
things are shifted to the left or right. I’ve no experience or theoretical 
knowledge confirming this, but your examples would fit such a description. 
Hence, I would guess NUMERIC to default to NUMERIC(9, 0).

I've confirmed that

SELECT CAST('2147483647' as numeric) FROM RDB$DATABASE
SELECT CAST('2147483647' as numeric(9,0) FROM RDB$DATABASE

both are accepted, whereas

SELECT CAST('2147483648' as numeric) FROM RDB$DATABASE
SELECT CAST('2147483648' as numeric(9,0) FROM RDB$DATABASE

are rejected.

HTH,
Set


RE: [firebird-support] Cast as Numeric without parenthesis

2015-03-26 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
then why here is an error?
 
SELECT CAST('123456789.23' as numeric) FROM RDB$DATABASE

Logically speaking I don't understand why

SELECT CAST('123456789.23' as numeric(9,0)) FROM RDB$DATABASE

is failing when

SELECT CAST('1.23' as numeric(1,0)) FROM RDB$DATABASE

succeeds.

Practically, I guess it means that Firebird first converts from a (var)char to 
an intermediate integer field before trying to round to nearest whole number, 
but I don't know why. 

Normally, I don't store numbers in strings, and 

SELECT CAST(123456789.23 as integer) FROM RDB$DATABASE

succeeds.

Here, I find that 

SELECT CAST(123456789.12345678 as decimal) FROM RDB$DATABASE

succeeds, whereas

SELECT CAST(123456789.123456789 as decimal) FROM RDB$DATABASE

fails. I don't know why.

Sorry for not being able to shed any more light,
Set


RE: [firebird-support] Extract week of the year (within year)

2015-03-24 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
is possible to get week of the year within year?
I see that built in functions only support ISO-8601 (or i do not know some 
parameter)

Actually, Karol, “week within year” is not the week, Karol. 1 January could be 
week 53 and 31 December could be week 1. If you want to consider 1 January 
always as part of week 1 (even if that day could be the only day of week 1), 
I’d suggest you try something like:

select (extract(yearday from cast('1.1.2014' as date))-extract(weekday from 
cast('1.1.2014' as date)))/7+1
from rdb$database

If you want the first seven days of a week to always be week 1 (and changing 
which day a week start with for each year), you could drop the second EXTRACT.

HTH,
Set


RE: [firebird-support] How To Generate Auto Increment Number in SQL Itself ?

2015-03-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
HI Louis,

It's pretty cool, but i need only in SQL, that too same number for all records 
for same employee and next incremental number for all records of the another 
employee.

SET any help offered ?

The first thing that comes to mind, is EXECUTE BLOCK (which is basically a 
STORED PROCEDURE built dynamically and not stored anywhere and that can be used 
anywhere a SELECT can be used, at least for recent Fb versions) combined with a 
temporary table, i.e.

EXECUTE BLOCK RETURNS (output params) AS
DECLARE VARIABLE RowNo INTEGER;
DECLARE VARIABLE EmpCode Empcode type;
BEGIN
  RowNo = 1;
  FOR SELECT DISTINCT EmpCode
  FROM your entire where clause INTO :EmpCode DO
  BEGIN
INSERT INTO MyTempTable(RowNo, EmpCode) VALUES (:RowNo, :EmpCode);
RowNo = RowNo + 1;
  END
  FOR SELECT Whatever you want
  FROM MyTempTable MTT
  JOIN all your other tables
  WHERE your entire where clause
  INTO output params DO
SUSPEND;
END

It might also be possible to actually create a stored procedure similar to:

CREATE PROCEDURE (MyID whatever RETURNS (RowNo Integer) AS
BEGIN
  RowNo = SELECT RowNo
  FROM MyTempTable
  WHERE MyID = :MyID;
  IF (RowNo IS NULL) THEN
  BEGIN
RowNo = SELECT GetContext(SetContext(GetContext) --Don't have time now to 
find out exactly how
INSERT INTO MyTempTable(RowNo, MyID) VALUES(:RowNo, :MyID);
  END
END

Then you'd only use a LEFT JOIN to this stored procedure in your queries (this 
could be reusable for different queries, not tied to your particular query).

HTH,
Set


RE: [firebird-support] Hang On ExecuteNonQuery Using Firebird2.5 with visual studio 2010

2015-02-24 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
For iLoop as Integer=0 to grid.Rows.Count-1'Grid Has 100,000 Rows
'-Sometimes Hang Here Also-
rdr = Get_Reader(USP_CHECK_AND_GET_ITEM_EXIST('  
Mid(Trim(dicFields_Name.Item(SP_ITEM_CODES)), 1, 20)  ','  
Mid(Trim(dicFields_Name.Item(ITEM_PART_CODES)), 1, 20)  ','  
Mid(Trim(dicFields_Name.Item(ITEM_NAMES)), 1, 50)  ','  
Mid(Trim(dicFields_Name.Item(CUSTOM_PART_CODE)), 1, 20)  ','  
Mid(Trim(dicFields_Name.Item(CUSTOM_PART_NAME)), 1, 50)  ','  
Mid(Trim(dicFields_Name.Item(SALE_UNIT)), 1, 10)  ','  
Mid(Trim(dicFields_Name.Item(SALE_SUB_UNIT)), 1, 10)  ','  
Mid(Trim(dicFields_Name.Item(ITEM_LOCAL_TAX)), 1, 20)  ','  
Mid(Trim(dicFields_Name.Item(ITEM_GROUP)), 1, 50)  ','  
Mid(Trim(dicFields_Name.Item(ITEM_CATEGORY_ID)), 1, 50)  '), fbTrans, , 
myImportConnection)

...

If Is_Update=True Then
  If 
 Update_Item_Master(nItem_IDS,Item_Name,Rate,bla,bla,bla,myImportConnection)=True
  Then

...

Public Function 
Update_Item_Master(Var1,Var2,Var3,Bla,Bla,Bla,myImportConnection)
Try
'Insert Statement
 PrePare_Column_Parameter_And_Values

            Using fCommand As FbCommand = myImportConnection.CreateCommand
                fCommand.Cancel()
                fCommand.CommandText = Insert Into M_ITEM(  
strColumns.ToString.TrimEnd(,)  ) Values(  
strValues.ToString.TrimEnd(,)  )
                fCommand.Connection = myImportConnection
                fCommand.CommandType = CommandType.Text
                fCommand.Transaction = fbTrans
                myResult = fCommand.BeginExecuteNonQuery(Nothing, Nothing)
                
   'While Not myResult.IsCompleted
                    'Me.Text = lblInvoice_Caption.Text  [Processing Row No. 
 Row_No.ToString()   - Adding In Item Master]
                'End While
                'iError = fCommand.EndExecuteNonQuery(myResult)
   
   iError = fCommand.ExecuteNonQuery() '---Hang In THis 
 Line
                fCommand.Parameters.Clear()
     End Using
   Return True 
Catch ex as Exception
   return False
Finally
End Try
End Function

Thanks, though not quite the type of code I'd expected (I'd expected more SQL 
and less VB). I notice a couple of things:

a) You try to insert when Is_Update is true (not false)
b) You create a completely new statement for each row

Now, I don't know whether or not it is deliberate to INSERT inside the 
Update_Item_Master function or not. What I do know, is that creating a new 
statement 10 times is considerably slower (though 10 hours would mean only 
three record per second and that would surprise me) than writing one statement 
with parameters, prepare it once and execute it 10 times with different 
parameter values.

I do not know VB and cannot give much other hints from this code, I guess the 
problem could either be on the Firebird side (you could show us more 
Firebird-related code, e.g. the source of SP_ITEM_CODES if that is a Firebird 
stored procedure, or one of the troublesome INSERT queries that you end up 
creating (i.e. strColumns and strValues expanded) or on the VB side (this list 
cannot help with VB issues).

Set


RE: [firebird-support] Hang On ExecuteNonQuery Using Firebird2.5 with visual studio 2010

2015-02-23 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
update never fails but it fails in insert query. loop run in a single 
connection with a new datarows in same query.

I think it is about time to show us some code (not all). Could it be that 
another transaction not visible to your current transaction has inserted a row 
that creates a lock conflict with your insert and that your code repeatedly 
tries (and fails) to insert? Or that it is a real deadlock, where one 
transaction first successfully updates record A, then fails on record B, 
whereas another transaction has successfully updated record B and fails on 
record A?

Typically, there would be no problems on INSERT, whereas UPDATE could create 
problems. Getting the problem on INSERT, I'd say indicates some kind of lock 
conflict which means that you have some UNIQUE field or constraint or don't use 
generators to populate your primary key.

Set


RE: [firebird-support] Hang On ExecuteNonQuery Using Firebird2.5 with visual studio 2010

2015-02-23 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
please, somone guide me where i am wrong
 
 This support list is for the Firebird database.  For the .NET 
 providers, you need to subscribe to the firebird-net-provider list:
 List-Subscribe:
 https://lists.sourceforge.net/lists/listinfo/firebird-net-provider,

At first glance it sounds like a lock conflict with a wait transaction, which 
is not specific to .net. 
To me this list would seem to be better unless and until it requires .net 
provider specific information.

If it is a lock conflict, then the process would hang on one out of 100 000 
records. Using wait transaction(s) for batch processing of 100 000 records may 
not be a good idea, in most cases it would be better to return back some error 
in a log and continue processing those records that succeed. Though we don't 
yet know whether or not it is a lock conflict. I'd recommend Sukhen to change 
from WAIT to NO WAIT (if this is an issue) and if this doesn't help, to give us 
further information:

Does the update process successfully process some record before taking 
extremely long on one record? Does the update process sometimes succeed within 
minutes or an hour or two, but then suddenly take over 10 hours? Are you 
constructing a new query for every insert/update and use 10 transactions or 
even connections, or do you have one UPDATE OR INSERT statement using 
parameters all running inside the same transaction (or even declaring an 
external table for the import)?

Set


RE: [firebird-support] Hang On ExecuteNonQuery Using Firebird2.5 with visual studio 2010

2015-02-23 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Sukhen wrote:
update never fails but it fails in insert query. loop run in a single 
connection with a new datarows in same query.

I answered:
I think it is about time to show us some code (not all). Could it be that 
another transaction not visible to your current 
transaction has inserted a row that creates a lock conflict with your insert 
and that your code repeatedly tries (and fails)
to insert? Or that it is a real deadlock, where one transaction first 
successfully updates record A, then fails on record B,
whereas another transaction has successfully updated record B and fails on 
record A?

Typically, there would be no problems on INSERT, whereas UPDATE could create 
problems. Getting the problem on INSERT, I'd say 
indicates some kind of lock conflict which means that you have some UNIQUE 
field or constraint or don't use generators to 
populate your primary key.

Sukhen answered:
is it could be any buffersize/memmroy issue. please, suggest if it is how to 
check it in firebird
please, somebody help me out

I didn't answer because I know nothing about buffersize/memory issues with 
Firebird (other than knowing that buffersize/memory very rarely causes problems 
with Firebird itself, don't know about the components you use in VB to connect 
to Firebird).

Normally, INSERTs would never fail. When they fail, that indicate some 
duplicate in a unique index or constraint or primary key (though that ought to 
give an error rather than be time consuming). Or it could possibly be an 
infinite loop. INSERTs can be slow, depending on complexity. Show us some code, 
I'm particularly interested in the INSERT that fails and the table definitions 
for the tables that the INSERT refers to.

Set


RE: [firebird-support] Multiple WHERE clauses

2015-02-22 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
You may consider

WITH TMP(My72, cFrom, cTo, dValueFrom, dValueTo) as
(SELECT CAST(:My72 as integer), US1.dValue, US2. dValue FROM RDB$DATABASE
LEFT JOIN dSetValue('Current Year', 'From') US1 ON (1=1)
LEFT JOIN dSetValue('Current Year', 'To') US2 ON (1=1))
SELECT whatever
FROM TMP t
CROSS JOIN tDevelopment d
WHERE d.iID = t.My72 OR
  (t.MyParam is null AND CAST(d.tDT AS DATE) BETWEEN t.dValueFrom, 
t.dValueTo)

I’ve assumed the dSetValue procedure returns 0 or 1 record. I did this because 
the way you wrote things, the procedure would be executed twice for every row 
in tDevelopment, something not necessary unless result of the procedure depends 
on values in tDevelopment (which it doesn’t in your case, since ‘Current Year’, 
‘From’ and ‘To’ are constants).

HTH,
Set

From: firebird-support@yahoogroups.com [mailto:firebird-support@yahoogroups.com]
Sent: 23. februar 2015 06:25
To: firebird-support@yahoogroups.com
Subject: [firebird-support] Multiple WHERE clauses



Hi all

I have a SELECT statement which needs to have a WHERE clause adapt if a 
variable has a value or not:

WHERE CASE WHEN 72  0 THEN tDevelopment.iID = 72
ELSE (CAST(tDevelopment.tDT AS DATE) BETWEEN (SELECT US1.dValue
FROM dSetValue('Current Year', 'From') US1)
AND (SELECT US2.dValue
FROM dSetValue('Current Year', 'To') US2)) END

The value 72 is variable.  What I need to do is when this value is a non zero I 
want to get only one record which matches the variable value and iID



ELSE I want it to adapt to get a range of records as per stored dates



Can we have such a WHERE clause?  (The one above does not work for me)  What if 
there are more such varied conditio ns to apply?



Please advise



Thanks and regards

Bhavbhuti








[Non-text portions of this message have been removed]



RE: [firebird-support] Charset in ISQL: How to show special characters

2015-02-19 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
my impression was the other way arround ;-)

Then I'm either misreading your e-mail, or you've switched the examples around?

When I change the charset in isql to any charset, that is definitly not 
used in the database I always get the same output from isql. I was 
expecting that the presentation of the same data (= varchar with 
special
characters) would change in isql if I switch charset.

What application is show  ö  and what isn't? And is that valid?

Two further questions: Was the field that you imported into defined with 
ISO8859_1 at the time of import or is this something that has changed later? 
And how did you import (I don't know if this second question matter, just 
wondered if you did something very unusual).

Set


RE: [firebird-support] Know nothing - please help

2015-02-18 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I have a query like this:

select
   artikli.a_sif,
    v1.v_txt,
    v2.v_txt,
    coalesce(sum(magkol.k_total),0) total,
    coalesce(sum(magkol.k_nabcen * magkol.k_total),0) vrednost,
    coalesce(sum(magkol.k_nabcen * magkol.k_total),0)/ 
coalesce(sum(magkol.k_total),1) nc,
    coalesce(sum(izlaz.i_kol),0) P_kom
from artikli
   left outer join izlaz on (artikli.a_id = izlaz.i_id) 
   left outer join magkol on (artikli.a_id = magkol.k_art) and magkol.k_mag0
   right outer join vrste v1 on v1.v_id=artikli.a_vrs
   left outer join vrste v2 on v2.v_id=v1.v_nad
   where artikli.a_sif='R3728'
group by 1,2,3

everyting works OK, except that last sum() : 

    coalesce(sum(i zlaz.i_kol),0) P_kom
 
It gives me sum result muliplied with number of occurences of that article ID 
in magkol table.

Well, it may not be what you want, Zoran, but it is what you ask for.

To rather get what you want, you could try changing your query to something 
like:

with tmp(a_sif, P_kom) as
(select a.a_sif, coalesce(sum(i.i_kol), 0)
 from artikli a
 left join izlaz I on a.a_id = i.i_id
 where a.a_sif='R3728'
   and exists(select * from vrste v where v.v_id=a.a_vrs))
select
a.a_sif,
v1.v_txt,
v2.v_txt,
coalesce(sum(m.k_total),0) total,
coalesce(sum(m.k_nabcen * m.k_total),0) vrednost,
coalesce(sum(m.k_nabcen * m.k_total),0)/ coalesce(sum(m.k_total),1) nc,
t.P_kom
from artikli a
join tmp t on a.a_sif = t.a_sif
join vrste v1 on v1.v_id=a.a_vrs
left join magkol m on a.a_id = m.k_art) and m.k_mag  0
left join vrste v2 on v2.v_id=v1.v_nad
group by 1, 2, 3, 7

Note that I removed your right join since your where clause logically and 
practically makes it an inner join. Not knowing your data, I don't know whether 
the EXISTS can be removed or not or if you can replace some of the left joins 
with simply join.

HTH,
Set


Re: [firebird-support] Query too slow

2015-02-18 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi;

I am using FB 2.5.3. in a fast environment (win8 64bit - QuadCore 3.4 Ghz - 8 
GB ram).

If I run this query it goes very very fast and returns 84 records:

Preparing query: select distinct PROC from GEST where (GEST.FSAL 
between '20080801' and '20080812') order by PROC
Prepare time: 0.007s
Field #01: GEST.PROC Alias:PROC Type:STRING(10)
PLAN SORT ((GEST NATURAL))

But if I run this one, it will return 84 records but it needs 10 minutes !!!:
Preparing query: select PROC.PROC from PROC where (PROC.PROC in (
select distinct PROC from GEST where (GEST.FSAL between '20080801' and 
'20080812'))) order by PROC
Prepare time: 0.003s
Field #01: PROC.PROC Alias:PROC Type:STR ING(10)
PLAN SORT ((GEST NATURAL))
PLAN (PROC ORDER PROC_PK)

Executing...
Done.
-1258819480 fetches, 0 marks, 28351438 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 11439 index, 962254304 seq.
Delta memory: 25308 bytes.
Total execution time: 0:10:53 (hh:mm:ss)
Script execution finished.

PROC is a table with 11400 rows. Even if the query optimizer takes the worse 
path (analizing one by one) it seems that 10 minutes is too much ... 
In my opinion, both may run very quick. Why is the second one taking that 
long?.

Well, your query does tell Firebird to find the DISTINCT possible values of 
PROC in a subset of GEST 11400 times. Sure, an ideal optimizer would have been 
able to see that your subselect wasn't correlated (not referencing the outer 
select) and that you didn't really bother about whether the subselect returned 
distinct records or not. Newer versions of Firebird do try to transform 
IN(SUBSELECT) into EXISTS(SELECT...), but I guess that your DISTINCT makes it 
give up. I think someone once told (probably Ann) that one of the early 
InterBase betas (or maybe it was even before that) had an optimizer that always 
chose the quickest way to return a result set. It's only problem was that it 
could use days to find which way was the quickest!

There are several fair ways to reach the result you want:

1) The standard way to write your type of query
select p.PROC from PROC p
where exists(select * from GEST g where g.PROC = p.PROC and g.FSAL between 
'20080801' and '20080812')
order by PROC

2) Quicker than option 1, but the result could differ a bit and you may want to 
add DISTINCT
select p.PROC
from PROC p
join GEST g on p.PROC = g.PROC
where g.FSAL between '20080801' and '20080812'

3) Logically similar to your original query in that you treat things like two 
statements and put them together. A nice way to do things if you construct your 
SQL dynamically.
with tmp(PROC) as
(select distinct PROC from GEST where (FSAL between '20080801' and '20080812')
select p.PROC from PROC p
join tmp g on p.PROC = t.PROC

Myself, I sometimes use IN (constant values) (I even used it earlier today), 
but I stopped using IN(subselect) after 1 or 2 attempts 15 years ago. I've 
never missed it since.

By the way, your original query can benefit from an index for GEST.FSAL, but 
cannot use an index for PROC.PROC. My second and third suggestion above could 
use indexes for GEST.FSAL and PROC.PROC, whereas my first suggestion only could 
use indexes for GEST.FSAL and GEST.PROC.

HTH,
Set

SV: [firebird-support] Re: Grouping without sorting alphabetically

2015-02-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Thanks Set for starting me on the right track.  Please see my finalized query 
below which gets me to the expected result.

Good to see that you got the result you wanted, Bhavbhuti! I do have two 
comments regarding your final result:

1) Why do you use ORDER BY within the CTEs? In the outer select, yes, there 
ORDER BY is useful, but within a CTE, I think ORDER BY is mainly useful in 
combination with window functions, which aren't available until Firebird 3. 
With CTEs like yours, I'd say avoid ORDER BY within the CTE.

2) Using cteFinalOrder is of course one possible option. However, I think it 
would be simpler to read the code if you just had joined cteTestGroups and 
cteTitleOrder directly in your main select. Though I do admit that is a matter 
of preference, and there's nothing wrong in using cteFinalOrder like you do.

Set

Re: [firebird-support] How to join records

2015-02-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
 On Feb 16, 2015, at 4:22 AM, josef.gschwendt...@quattro-soft.de 
 [firebird-support] firebird-support@yahoogroups.com wrote:

 we have 2 tables
 For each record in Table1 there are 2 records in Table2.

 Table1 (T1)
 ==
 1
 2


 Table2 (T2)

 T2T1
 ==
 11
 21
 32
 42

 What is the cheapest way to get a dataset like below?

 T1T2aT2b
 ===
 1   12
 2   34


Can't guarantee it's the cheapest, but you might try

select T1.T1, max T2.T1 T2a, max T2.T2 T2B
from T1
  inner join T2 on T1.T1 = T2.T1
  group by T1.T1

I think Ann meant

select T1.T1, min(T2.T2) T2a, max(T2.T2) T2b --use quotation marks only if 
you want case sensitivity or special characters in the names, if not it is 
better to skip them
from T1
join T2 on T1.T1 = T2.T1
group by T1.T1

An alternative to this if there are always two matching records, is:

select t1.t1, t2_1.t2 T2a, t2_2.t2 T2b
from t1
join t2 t2_1 on t1.t1 = t2_1.t1
join t2 t2_2 on t1.t1 = t2_2.t1 and t2_1.t2  t2_2.t2

Don't know how these two options compare performancewise, I guess Anns solution 
is quicker or equally quick. Anns solution will work if the number of matches 
varies (mine won't), whereas mine more easily extends to include other fields 
matching t2a and t2b. Needless to say, both Anns and my solution can be 
modified so that they will fit other situations. For more complex situations, 
you may want to consider EXECUTE BLOCK.

Set

RE: [firebird-support] Re: Grouping without sorting alphabetically

2015-02-13 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Dataset:
1Haemogram Report  1Routine 
Haemogram
1Haemogram Report  5Diff. Count 
(Mature Cells)
1Haemogram Report  10   Special 
Investigations
2Haemogram Report  1Diff. Count 
(Mature Cells)
3C-Reactive Protine1
4Urine Analysis1Physical 
Examination
4Urine Analysis8Chemical 
Examination
4Urine Analysis10   Microscopic 
Examination of Centrifugalised Deposit
5Haemogram Report  1E.S.R.
 
Bhavbhutis attempt:
WITH cteTestGroups AS (SELECT MIN(A.iSrNo) AS iGroupSrNo
, B.cTitle
, MIN(C.iSrNo) AS iSubGroupSrNo
, C.cSubGroup
FROM sReqSlipTestGroup A
JOIN mTestGroups B
ON  B.iID = A.iTestGroupID
JOIN lTestGroupsTest C
ON C.iPID = B.iID
JOIN mTests D
ON D.iID = C.iTestID
WHERE A.iPID = 1
GROUP BY B.lNewPage
, A.iSrNo
, B.cTitle
, C.cSubGroup
ORDER BY 1, 2, 3, 4)

SELECT cteTG.*
FROM cteTestGroups cteTG

My final output I want something like this:
1    Haemogram Report      1    Routine 
Haemogram
1    Haemogram Report      5    Diff. Count 
(Mature Cells)
1    Haemogram Report      10   Special 
Investigations
5    Haemogram Report      1    E.S.R.
3    C-Reactive Protine        1
4    Urine Analysis        1    Physical 
Examination
4    Urine Analysis        8    Chemical 
Examination
4    Urine Analysis        10   Microscopic 
Examination of Centrifugalised Deposit

ie.  The Row 4 is merged with row 2 and row 9 becomes row 4

The idea is that all the cTitle are clubbed together but in the order they 
were originally selected, thus MIN(A.iSrNo).
The second grouping is cSubGroup, together but in the order they were defined, 
thus MIN(C.iSrNo)

I think an additional CTE may be what you want:

WITH cteTestGroups (iGroupSrNo, cTitle, iSubGroupSrNo, cSubGroup AS
(SELECT MIN(A.iSrNo), B.cTitle, MIN(C.iSrNo), C.cSubGroup
 FROM sReqSlipTestGroup A
 JOIN mTestGroups B ON B.iID = A.iTestGroupID
 JOIN lTestGroupsTest C ON C.iPID = B.iID
 JOIN mTests D ON D.iID = C.iTestID
 WHERE A.iPID = 1
 GROUP BY B.lNewPage, A.iSrNo, B.cTitle, C.cSubGroup),
 cteOrderGroups(cTitle, cOrder) AS
 (select cTitle, min(iGroupSrNo)
  from cteTestGroups
  group by 1)
        
SELECT cteTG.*
FROM cteTestGroups cteTG
JOIN cteOrderGroups cteOG on cteTG.cTitle = cteOG.cTitle
ORDER BY cteOG.cOrder, cteTG.iSubGroupSrNo

Maybe things could be simplified further, but this at least ought to work.
Set


RE: [firebird-support] Re: Speed issues

2015-02-09 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I am having similar issues. Are there any resources to read up on this?

What do you mean by similar issues, Louis? Zoran first showed us his SQL and 
plan, so that we more or less could see that his SQL, plan and indexes seemed 
good (that's arguably the most common reason for speed problems). Unfortunately 
I don't know of any generally good resources for fixing speed issues with 
Firebird (excepting this list and sometimes firebird-devel, possibly The 
Firebird book by Helen Borrie can have some tips as well, I don't know), and I 
doubt there exist any good resources focusing particularly on speed problems 
with big tables (whereas I cannot rule out there could exist some good 
resources for more general speed problems).

I never answered Zorans question since I've no experience with tables with more 
than 100 million rows and Seans answers seemed sensible. I noticed two things 
that they haven't discussed (but that I don't know how relevant would be) and 
that is that we haven't seen the DDL of his tables (wondering whether any of 
the tables involved have lots of fields or large CHAR and VARCHAR fields that 
could affect performance) and that we don't know how many rows would be 
returned from the same query if DISTINCT was removed.

Set


Re: [firebird-support] nesting - weight calculation

2015-01-29 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
There is at least a good alternative, Frank Ingermann showed how to do 
something very similar when calculating the amount of ingredients required when 
baking a marble cake at a Firebird conference a few years ago. He used a 
recursive CTE. Whether a recursive CTE is simpler than a recursive procedure or 
not depends partly on implementation, partly on what you mean by simple and 
partly on who you ask. I liked Franks solution.

Set 
__

Hello,

there is a table with all Material (stock), each one has a number. Now, in a 
second table there is listed the material that is a part of the Material.

For example:

Material ABC
Material BCD
Material XXX
Material OMV
Material KOM

Material OMV can be a Part of XXX and XXX a Part of ABC, of course the BCD can 
assigned to XXX, OMV, ABC.

Now I would like to know what is the total weight of the main material, (total 
weight from abc + amount of bcd + amount of xxx

ABC has 2 XXX, XXX has 2 OMV
Now we have 1 X ABC, 2 times XXX and 4 X OMV, OMV weighs 0,5kg and so on

The structure

Table Mainmaterial
PartNo
Description

Table Material
PartNo of Mainmaterial
PartNoA = assigned Material
Amount (of PartNoA)

Is there a simpler statement possible than my stored procedure (recursive)

Thank you.


Re: [firebird-support] Unlock record

2015-01-24 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I saw the same as you, and made the following test:

- Opened my application.
- Executed the option which locks a record (executes a SELECT * FROM TABLE1 
WHERE (FIELD1 = 'some value') WITH LOCK).
- Opened the database with IB_SQL.
- Looked in table MON$STATEMENTS. I found many records. Many of them with 
MON$SQL_TEXT null. Only one of them had MON$TIMESTAMP not null.
- I deleted the only record with MON$TIMESTAMP not null.
- I opened another instance of IB_SQL and verified that the record I locked at 
the first step was still locked.

Am I undestanding something wrong or this doesn´t work?

Another idea to manually unlock a record?

Regards

Eduardo

Finally got temporary access to a computer and can confirm that deleting from 
mon$statements is not enough when using WITH LOCK (I never use WITH LOCK 
myself). However, I did get access to this record (using Fb 2.5) by deleting 
from MON$ATTACHMENTS. There may or may not be other, less intrusive ways to get 
such access, though I failed when I tried MON$TRANSACTIONS.

Set

Re: [firebird-support] Unlock record

2015-01-22 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I looked in a database, and in MON$STATEMENTS tabla I have the following 
fields:

MON$STATEMENT_ID
MON$ATTACHMENT_ID
MON$TRANSACTION_ID
MON$STATE
MON$TIMESTAMP
MON$SQL_TEXT
MON$STAT_ID

How can I detect which is the record I have to delete to unlock my record? 
This is the only table I have to modify?

I typically just look at the mon$sql_text with a mon$timestamp that seems to be 
the correct one.

HTH,  Set

 Mensaje original ---
 May be I can modify or delete some record in any MON$ table or do some other 
 thing?

I typically locate and delete records from MON$STATEMENTS. Mind you, that is 
2.5 and typically when I have a long-
running query. Don't know whether deleting from this table is possible or safe 
with 2.1 or sensible WITH LOCK.


SV: [firebird-support] Unlock record

2015-01-20 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
 May be I can modify or delete some record in any MON$ table or do some other 
 thing?

I typically locate and delete records from MON$STATEMENTS.  Mind you, that is 
2.5 and typically when I have a long-running query. Don't know whether deleting 
from this table is possible or safe with 2.1 or sensible WITH LOCK. 

HTH, 

Set

Re: [firebird-support] working days between two dates

2015-01-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi Tomas! I just mean week days...

Something like DateDiff() but only counting from monday to friday.

I have a function in Delphi for that. I could make an UDF I think. I just 
wander if there is something already done. I thought it was something very 
used... probably is not?

I don't know whether this is common or not (can't remember anyone asking for it 
before on this list), but if you don't care about special days it could be 
implemented as simple as this:

execute block (fromdate date = :fromdate, todate date = :todate) returns 
(weekdays integer) as
  declare variable checkdate date;
begin
  weekdays = 0;
  checkdate = fromdate;
  while (checkdate = todate) do
  begin
if (checkdate  todate - 6) then
begin
  weekdays = weekdays + 5;
  checkdate = checkdate + 7;
end
else
begin
  if (extract(weekday from checkdate) between 1 and 5) then
weekdays = weekdays + 1;
  checkdate = checkdate + 1;
end
  end
  suspend;
end

There should be other ways to do this in Firebird as well (some of them 
better), this is just one way that quickly comes to mind.

HTH,
Set

[firebird-support] Re: Deadlock exception occurs but it shouldn't?

2014-12-25 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
The main purposes of explicit locks are (1) to prevent expensive handling of 
update conflict errors in heavily loaded application

this is the exact reason I try to avoid conflicts. My threads can wait but 
they should not raise exceptions.

I always though that it is possible to avoid such conflicts on the database 
level.

In some cases it might be possible to avoid lock conflickts by using INSERT 
rather than UPDATE. Typically, you may have a trigger or something similar that 
inserts into a summary table, and then you have a separate process running at 
regular intervals that update the summary tables. E.g. you could have an 
inventory table originally with three items, and then insert into this table 
when things are sold or bought.

Inventory
Product InStock
175 --Items originally in stock
2   350 --Items originally in stock
354 --Items originally in stock
1 -5 --Sold five items
1 -2 --Sold two items
3 -8 --Sold eight items
1   100 --Bought hundred more items
1 -3 --Sold three items

This does require programs using SUM(InStock) rather than just InStock when 
selecting, but you should never get lock conflicts. Every night (or every hour 
or week or whenever, just make sure it doesn't run several instances 
concurrently) you could run the following procedure:

CREATE PROCEDURE UpdateStock AS
  DECLARE VARIABLE id INTEGER;
  DECLARE VARIABLE NoOfItems INTEGER;
BEGIN
  FOR SELECT Product, sum(InStock)
  FROM Inventory
  GROUP BY 1
  INTO :id, :NoOfItems DO
  BEGIN
DELETE FROM INVENTORY
WHERE Product = :id;
INSERT INTO INVENTORY(Product, InStock)
VALUES (:id, :NoOfItems);
  END
END

Don't know whether this is applicable to your situation or not, but

HTH,
Set

[firebird-support] Re: performance of subselect with group by

2014-12-18 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hello,

  thanks Set, makes my test unnecessary!

  But I'm thinking a little bit about my original problem.

  Would it make sense to add a tracker entry for optimization of
  subselects without reference to outer query?

  I think that they should get evaluated and transformed to something
  like a or connected list of simple compares.

  So
  delete from test where Id in (
 select min(t.Id) FROM test t
 group by t.reference, t.key
 having count(*)  1
 )

  could be transformed by the engine to

  delete from test where Id = 5 or Id = 6 or Id = 89

  in case of

  select min(t.Id) FROM test t
  group by t.reference, t.key
  having count(*)  1

  would return 5,6,89

  I've found several similar questions in my mail archive so I think
  I'm not the only one with such a problem.

  A common use case would be to remove duplicate entries for
  example to create a unique index.

  Any comments?

My guess is that it is too early to add this to Firebird. Sure, there are 
situations where a non-correlated subselect would be benefitial, but how would 
Firebird know when? In your case (since you're deleting from the same table as 
you're selecting from), I agree that this could be simple. However, normally 
the select would be against a different table and then I think things are not 
as simple. Assuming we were talking about two different tables: I don't know 
how Firebird translates a query like yours into EXISTS, but theoretically it 
could be something like:

delete from DeleteFromTable t
where exists(select * from test t2
 left join test t3 
on t2.reference = t3.reference
   and t2.key = t3.key
   and t2.id  t3.id
 where t.id = t2.id
   and t3.id is null)

If DeleteFromTable was a smallish table, and test was large and sensible 
indexes were in place, then my rewritten query would be quicker if your 'min 
subquery' returned a lot of rows. On the other hand, if your subquery returned 
few rows, then executing the subselect like you suggest would indeed be 
quicker. If you add a WHERE clause to your subselect, it is even thinkable 
that, say, WHERE MyField = 1 would be quicker using your solution, whereas 
WHERE MyField = 2 would be quicker using mine. And the only way for Firebird to 
know, would be to have histograms. Histograms was removed from things to be 
implemented in version 3 (I think it was announced during the conference, at 
least I'm certain that I've heard this), I hope they will appear in Firebird 4. 
I would think that once histograms are in place, cases like yours are amongst 
those that can be considered for optimization (although I don't know anything 
about the source of Firebird).

You are definitely not the only one with this kind of problem, I would 
appreciate it myself if it was possible for deletes and updates to use indexes 
similar to what is possible with selects (e.g. allowing for JOIN). However, my 
knowledge of SQL and Firebird is not good enough to formulate how to do this in 
a sensible way. Also, I think that as users of Firebird it is possible to 
rewrite our slow queries to more performant ones in most cases, so to me this 
problem is not all too big.

I have never needed expression indexes myself, but have you looked into writing 
one to see if this can make your query execute (considerably) faster?

Sorry for not agreeing with you in that this is a useful optimization just yet, 
if you're lucky people knowing something about the source code of Firebird will 
disagree with me.

Set

Re: [firebird-support] Performance optimation?

2014-12-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hello,

I save values in some tables (simpler description)

First a Table who saved the timestamp of the mensuration
Table A timestamps
ID primary key
TS timestamp

Second a Table with the measured data (25 records/measured sensors will be 
saved every 10 Minutes, one record in Table A, 25 in Table B)
Table B mensuration
ID primary key
ID_counter integer of item to measure
ID_Timestamp foreign key of Table A
Value (double precision)

Now I would like to make an analysis. At the time, I do this:

for select cast(ts as date) as mz from tablea where ts = “criteria from” and 
ts  “criteria to”
group by mz)
into :messzeit do
begin
  f_messwert = null;
  MESSWERTE = '';
  for select a.id_counter, sum(a.value) from tableb a left join tablea b 
 on a.id_timestamp = b.id
  where cast(b.ts as date) = :messzeit
  group by a.id_counter
  into :i_zae, :f_messwert do
  begin
if(f_messwert is null) then f_messwert = 0;
MESSWERTE = MESSWERTE || cast(:i_zae as varchar(4)) || '=' || 
 cast(:f_messwert as varchar(8)) || ';';
  end
  suspend;
end

The Result is one returned record for each day (day, conter 1 = 123; counter 2 
= 222;…)

It takes a long time but I must integrate the tablea on the second part of the 
statement. How can I optimize this in firebird?


One thing to notice, Olaf, is that where cast(b.ts as date) will never use an 
index (if you have an index on TS). I would suggest changing that part of the 
query to something like:

where cast(b.ts as date) = :messzeit
   and b.ts between :messzeit and :messzeit + 1

The first line limits the result to what you want, the second uses an index (if 
you have one).

Maybe you could replace your two 'for select's with one, like this:

begin
  messzeit2 = null;
  for select cast(a.ts as date), b.id_counter, sum(b.value) 
  from tableb b 
  join tablea a on b.id_timestamp = a.id
  where a.ts = “criteria from” and a.ts  “criteria to”
  group by 1, 2
  into :messzeit, :i_zae, :f_messwert do
  begin
if (messzeit  messzeit2) then
begin
  messzeit2 = messzeit;
  f_messwert = null;
  MESSWERTE = '';
end
if(f_messwert is null) then f_messwert = 0;
MESSWERTE = MESSWERTE || cast(:i_zae as varchar(4)) || '=' || 
cast(:f_messwert as varchar(8)) || ';';
  end
  suspend;
end

Does this work, and is it any faster?

If this is a new project that should end up with a database lasting for quite 
some time, I would recommend you to reconsider your primary key. The reason 
being that primary keys ought to never have any business meaning (doesn't 
really matter if it is an integer, GUID or whatever). If you are certain that 
requirements will never change, then fine, but if things later could change so 
that there could be several records with the same timestamp, then this is 
something that is considerably simpler to fix if the timestamp is not a primary 
key.

HTH,
Set





++

Visit http://www.firebirdsql.org and click the Documentation item
on the main (top) menu.  Try FAQ and other links from the left-side menu there.

Also search the knowledgebases at http://www.ibphoenix.com/resources/documents/ 

++


Yahoo Groups Links

* To visit your group on the web, go to:
http://groups.yahoo.com/group/firebird-support/

* Your email settings:
Individual Email | Traditional

* To change settings online go to:
http://groups.yahoo.com/group/firebird-support/join
(Yahoo! ID required)

* To change settings via email:
firebird-support-dig...@yahoogroups.com 
firebird-support-fullfeatu...@yahoogroups.com

* To unsubscribe from this group, send an email to:
firebird-support-unsubscr...@yahoogroups.com

* Your use of Yahoo Groups is subject to:
https://info.yahoo.com/legal/us/yahoo/utos/terms/



[firebird-support] Re: performance of subselect with group by

2014-12-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hello,

  Thanks for the answer.
  How can I optimize if I want to use a DML command in conjunction
  with a subselect, e.g.

 delete from test where Id in (
 select min(t.Id) FROM test t
 group by t.reference, t.key
 having count(*)  1
 )


Hi  Björn!

I don't think there is any simple way to make a delete with a subselect as the 
only part of a where clause perform great on largish tables. That is, using 
EXECUTE BLOCK (which doesn't exist on older Firebird versions) should perform 
OK:

execute block as
  declare variable id integer;
begin
  for select min(t.Id) FROM test t
  group by t.reference, t.key
  having count(*)  1
  into :id do
delete from test where Id = :id;
end

HTH,
Set

[firebird-support] Re: performance of subselect with group by

2014-12-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
  I don't think there is any simple way to make a delete with a
 subselect as the only part of a where clause perform great on
 largish tables. That is, using EXECUTE BLOCK (which doesn't exist on
 older Firebird versions) should perform OK:

  execute block as
declare variable id integer;
  begin
for select min(t.Id) FROM test t
group by t.reference, t.key
having count(*)  1
into :id do
  delete from test where Id = :id;
  end

  HTH,
  Set

  well, that's not the answer I wanted to get, but I've to deal with
  that fact.

  I've to check wether EXECUTE STATEMENT can execute EXECUTE
  BLOCKs, as the DELETE Statement is build dynamically in a proc.

Interesting, Björn, I'd expect execute block to work wherever a query could be 
used, but hadn't tried it inside EXECUTE STATEMENT until you said you would 
have to try. However, it made me curious, so I wrote:

execute block returns(myanswer varchar(32)) as
declare variable es varchar(500);
begin
  es = 'execute block returns(ma varchar(32)) as ' ||
   '   declare variable es2 varchar(500); ' ||
   ' begin ' ||
   '   es2 = ''execute block returns(ma2 varchar(32)) as ' ||
   '   begin ' ||
   ' select Hooray from rdb$database into ma2; ' ||
   ' suspend; '||
   '   end''; ' ||
   '   execute statement es2 into :ma; ' ||
   '   suspend; ' ||
   ' end';
  execute statement es into :myanswer;
  suspend;
end 

just to see if it worked. It actually returned Hooray, so yes, EXECUTE 
STATEMENT can execute EXECUTE BLOCK and they can even be nested within each 
other!

Set

Re: [firebird-support] group by date

2014-12-14 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Any ideas?

Hello @ll,

I would like to group my records by day or month. The date is saved as 
timestamp. If I do the following,

SELECT EXTRACT(day FROM m.messzeit), COUNT(*) as CountMessages
FROM te_messzeiten m

GROUP BY EXTRACT(day FROM m.messzeit)

I get all days (1 to 31), but I need group by 1.1.2014, 2.1.2014.. – daily 
bzw. 1 2014, 2 2014 – monthly

How can I realize this?

A few minutes after you asked this question, Mark gave you a very good answer:

group by day:

GROUP BY CAST(m.messzeit AS DATE)

or less efficient:

GROUP BY EXTRACT(YEAR from m.messzeit), (EXTRACT(month FROM m.messzeit),
EXTRACT(day from m.messzeit)

or if you want to group by month in year:

GROUP BY EXTRACT(YEAR from m.messzeit), (EXTRACT(month FROM m.messzeit)

Mark





++

Visit http://www.firebirdsql.org and click the Documentation item
on the main (top) menu.  Try FAQ and other links from the left-side menu there.

Also search the knowledgebases at http://www.ibphoenix.com/resources/documents/ 

++


Yahoo Groups Links

* To visit your group on the web, go to:
http://groups.yahoo.com/group/firebird-support/

* Your email settings:
Individual Email | Traditional

* To change settings online go to:
http://groups.yahoo.com/group/firebird-support/join
(Yahoo! ID required)

* To change settings via email:
firebird-support-dig...@yahoogroups.com 
firebird-support-fullfeatu...@yahoogroups.com

* To unsubscribe from this group, send an email to:
firebird-support-unsubscr...@yahoogroups.com

* Your use of Yahoo Groups is subject to:
https://info.yahoo.com/legal/us/yahoo/utos/terms/



RE: [firebird-support] Grouping SQL counts

2014-12-11 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
FB 1.5x

I have a SQL statement that returns the results I want--giving me a count on 
the detail dataset 
(ClientRegHistList is a detail list on ClientRegHis, more info below) 

  select C.RegDate, Count(Client_ID)
    from ClientRegHist C,
 ClientReghistList CL
   where (CL.ClientRegHist_ID = C.ClientRegHist_ID)
 and CL.RegType = 0
 and (C.Company_ID = 128)
group by 1;

I have a second SQL that is exactly the same except changing the 0 to a 1 
in line 5.  I would like to combine the two datasets into o ne result set--any 
hints on how to do this?

Thank you,

Ed Dressel

Huan is right in that your problem description is ambiguous, Ed, there are 
several possible answers to your question. However, I think there are a limited 
number of possible ways to read your question, so below are a couple of 
possibilities that may or may not work. My memory is poor, I haven't used Fb 
1.5 for one or two years and I'm never use COUNT(fieldname) myself (I always 
use COUNT(*) or COUNT(DISTINCT fieldname), so no guarantees that all four of 
them will work. Even though not strictly speaking required, I also changed from 
SQL-89 to SQL-92 (explicitly using JOIN rather than joining in the WHERE 
clause).

a) Getting the sum of 0 and 1:

  select C.RegDate, Count(Client_ID)
from ClientRegHist C
join ClientReghistList CL on CL.ClientRegHist_ID = C.ClientRegHist_ID
   where CL.RegType in (0, 1)
 and C.Company_ID = 128
group by 1;

b) Counting each separately:

  select C.RegDate, CL.RegType, Count(Client_ID)
from ClientRegHist C
join ClientReghistList CL on CL.ClientRegHist_ID = C.ClientRegHist_ID
   where CL.RegType in (0, 1)
 and C.Company_ID = 128
group by 1, 2;

c) Having all the lines of both queries in the same result set (you may not be 
able to separate them):

  select C.RegDate, Count(Client_ID)
from ClientRegHist C
join ClientReghistList CL on CL.ClientRegHist_ID = C.ClientRegHist_ID
   where CL.RegType = 0
 and C.Company_ID = 128
group by 1
union all
  select C.RegDate, Count(Client_ID)
from ClientRegHist C
join ClientReghistList CL on CL.ClientRegHist_ID = C.ClientRegHist_ID
   where CL.RegType = 1
 and C.Company_ID = 128
group by 1;

d) Having one column for each in the result set:

  select C.RegDate, Count(case when CL.RegType = 0 then Client_ID else null 
end) as RegType0, Count(case when CL.RegType = 1 then Client_ID else null end) 
as RegType1,
from ClientRegHist C
join ClientReghistList CL on CL.ClientRegHist_ID = C.ClientRegHist_ID
   where CL.RegType in (0, 1)
 and C.Company_ID = 128
group by 1;

Do any of these four answer your question?

HTH,
Set


Re: [firebird-support] Like and database entry -

2014-12-10 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
where name like 'Ab%' returns any entry of the table, where name start with 
Ab except those ones containing character -. Using starting with or 
containing 
the same database entries are missing.

Firebird simply doesn't exclude entries depending on which character follows 
what you're searching for. It might be like Helen said (different case) or 
maybe it can be something like a damaged index. Fb 2.5.1 has a problem with 
multifield indexes that can contain null, and I wouldn't surprise me if this 
could lead to apparently missing records (although I haven't heard or 
experienced this, just that GROUP BY can return duplicates). If you are using 
Fb 2.5.1 or the database has been in Fb 2.5.1 and you haven't restored the 
database since, then either upgrade to a newer version (and backup/restore your 
database) or try avoiding multi-field indexes.

If this isn't the case, Rainer, then please provide us with a more detailed 
description of your problem, including DDL of the table, your SQL statement, 
chosen PLAN and a few examples of records that should be returned including 
some that aren't. Also, it might be helpful if you include which Firebird 
version, character set and collation you are using. Many of us would be greatly 
surprised (an understatement) if you could provide a reproducible test case 
demonstrating such a severe Firebird error.

HTH,
Set

RE: [firebird-support] Re: Firebird database seems to influence multi user ability

2014-12-09 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I have been an interbase guy about fifteen years ago and loved to see it go 
open source. I used to work with Paul Beach (Hello, if you're here,Paul)

Yes, Paul Beach is still here, he’s working with other InterBase and Firebird 
experts at IB Phoenix. Here you can see who they are: 
http://www.ibphoenix.com/about/contact

another mystery to me. First of all, I was using SYSDBA for all of my actions. 
It worked with masterkey! 
As far as I remember this should be changed in any serious software, shouldn't 
it?

Well, I could agree that no one ought to run with the default password. 
However, I would say that software should not automatically change the Firebird 
password. It is fine if your system is the only system on your computer using 
Firebird, but let’s say there already exists another program on your computer 
that uses Firebird, you install your program and change the password, then you 
may risk that the original program no longer works. Hence, I’d say some kind of 
intelligence ought to be present when installing Firebird, and leaving this 
responsibility to a human administrator of the machine is one common way to do 
it (it may vary depending on what your system does). A system ought to tell the 
users how to install Firebird and change password. Of course, they can also 
provide a Firebird installer if they want to. If they do, they could change the 
password when installing Firebird, but never do any automatic change of the 
SYSDBA password to an existing system.

Using the default password makes your database vulnerable to anyone with access 
to the database, but generally you should limit who has access to your database 
and only give access through aliases so that no one knows where the database is 
physically stored. Then the vulnerability will be limited to those who have 
access. Of course, SYSDBA can normally look at, modify or delete any object. In 
many cases this will be very bad, in other cases it might not matter equally 
much. If anyone gets physical access to your Firebird database, then you may 
consider all sensitive data lost. Put a copy of the database on any machine, 
install Firebird and you get access with the default password.

Another thing is that I was looking into the tables  and missed RDB$user. The 
table just is not there. Did that change recently?

Are you sure that RDB$USER was a table? I’m used to users being defined in the 
Firebird server itself (probably stored in security2.fdb in your case, 15 years 
ago I think it will have been isc4.gdb), whereas their rights to any object in 
a database is stored in the database itself (probably in RDB$USER_PRIVILEGES, 
although I must admit I don’t know). I don’t quite understand what an RDB$USER 
table in your own database should be used for, although, again, I must admit 
that my knowledge of the system tables are limited to what I’ve used myself 
(which doesn’t include RDB$USER).

HTH,
Set


RE: [firebird-support] Why this similar to is wrong?

2014-11-25 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
select 
iif('em...@testdomain.com' similar to 
'([_a-zA-Z\d\-\.]+@[_a-zA-Z\d\-]+(\.[_a-zA-Z\d\-]+)+)','ok','fail')
from rdb$database

Says 'invalid string' and 'invalid pattern', but the pattern it´s the same in 
other languages for validate email address.

I know nothing about regular expressions, but 
http://www.firebirdsql.org/refdocs/langrefupd25-similar-to.html#langrefupd25-similar-to-building-regexps
says There is no default escape character; rather, the user specifies one when 
needed:

and then gives four examples:

'Peer (Poire)' similar to 'P[^ ]+ \(P[^ ]+\)' escape '\'-- true
'Pera [Pear]'  similar to 'P[^ ]+ #[P[^ ]+#]' escape '#'-- true
'Päron-Äppledryck' similar to 'P%$-Ä%' escape '$'   -- true
'Pärondryck' similar to 'P%--Ä%' escape '-' -- false

HTH,
Set


RE: [firebird-support] Left outer join with stored procedure

2014-11-19 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hello All,

I have a table regioni with 164 rows (r_id), and also stored procedure which 
returns some data like (r_id, value).
When I try to use

select

regioni _ID,
stored_procedure_value

from regioni
left outer join stored_procedure (:DATE1,:DATE2)

I only get number 20 rows for the R_ID which is returned by procedure. I cant 
manage to get all 164 rows from regioni table matched with values from 
stored_procedure, where value exists.

Can someno help with this ?

If you provide more information, I’m sure someone on this list can help, Zoran, 
but I cannot see that the parts that you’ve provided so far contains any reason 
for only 20 rows to be returned (mind you, I’m not used to queries like yours, 
with only parameters in the call to stored_procedure – as far as I can see, 
this query ought to return the same stored_procedure_value for all rows). The 
most common reason for a problem like yours, is that the LEFT tuple is referred 
to in the WHERE clause (when it should be in the LEFT JOIN), but you don’t seem 
to have any WHERE clause. By the way, I expect regioni_ID to be the same as 
R_ID?

Set


RE: [firebird-support] Re: Cross database update

2014-11-17 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Dear Thomas,
thank you for your answer. I have experienced that pssing by the trigger is 
functioning well.

The only thing wrong is that the loop has no effect on the data of the 
records. And I hoped that someone could check the statement syntaxwise. Maybe 
I am doing something wrong in my logic.

Is the use of the for select do loop correct as stated? Maybe I have to use an 
update or insert statement except?

Your FOR..SELECT seems fine, what’s unknown to us (proprietary to IB Expert) is 
the ibeblock and the use of two separate connections (Firebird does support 
transactions spanning several connections as well as ON EXTERNAL, but not 
treating two connections as something you can mix inside a stored procedure).

I think your error is in your execute block and that you either have to 
explicitly pass values or declare variables as input parameters in your execute 
block. Take a look at 
http://www.firebirdsql.org/refdocs/langrefupd20-execblock.html.
Moreover, I’d recommend trying to get some kind of error message rather than 
having no code in the EXCEPT block (hiding things from the user may be OK, it 
is normally not what you want when you have a problem puzzling you).

HTH,
Set


RE: [firebird-support] sum data into single row per day

2014-11-15 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Thank you Svein, that's what I tried but kept getting:
SQL error code = -104.
Invalid expression in the select list (not contained in either an aggregate 
function or the GROUP BY clause).

and yet it now works. I thought it must have been because I was accessing code 
in the iif(...). I must have had a typo that 
I could not see for looking. Anyway, that now works perfectly, without the ',' 
after SH.

Sorry about not removing the comma after copying. I think your error might have 
been doing IIF(SUM... rather than SUM(IIF... Logically, that is using an 
aggregate to decide which single value to return (and hence, needs to be 
grouped by), whereas SUM(IIF takes a single value to determine which value 
should be used in the aggregation and doesn't need aggregation. When I try 
IIF(SUM..., I do get -104 as well.

Set


RE: [firebird-support] sum data into single row per day

2014-11-14 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
   for select
 iif(n.code=1,sum(n.amount),0),
 iif(n.code=2,sum(n.amount),0),
 iif(n.code=3,sum(n.amount),0),
 n.sell_date
   from  new_table n
   where n.sell_date between :fromdate and :uptodate
   group by n.sell_date,n.code
   into
 :stock,
 :repair,
 :sh,
 :sell_date

This gives the correct totals but not in the correct format:

SELL_DATE  STOCK   REPAIR  SH
07.11.2014 0   0   30
10.11.2014 160 0   0
10.11.2014 0   20  0
11.11.2014 100 0   0
11.11.2014 0   22000
11.11.2014 0   0   500

What I want is this format, one row per day:

SELL_DATE  STOCK   REPAIR  SH
07.11.2014 0   0   30
10.11.2014 160 20  0
11.11.2014 100 2200500

You almost got it right, Alan, just remember to only group only on things you 
want to produce a separate row. This is the query you want:

select sell_date,
   sum(iif(code=1, amount,0)) stock,
   sum(iif(code=2, amount,0)) repair,
   sum(iif(code=3, amount,0)) SH,
from  new_table
where n.sell_date between :fromdate and :uptodate
group by sell_date

Set


[firebird-support] Re: Why does the optimizer choose NATURAL for this tiny table?

2014-11-13 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi Sean/Dmitry, I've mingled my answers to your suggestions.

Does the plan change to INDEX if the condition would be:

S2) on p.icd10 in (t.icd10, t.icd3)
S3) on p.icd10 = t.icd10 or p.icd10 = t.icd3
D2) ON p.icd10 = t.icd10 OR p.icd10 = t.icd10

No, these all keep the original plan:

PLAN JOIN (JOIN (JOIN (T KID INDEX (U_NPR_KRG_ID_FNRK), T N INDEX 
(I_NPR_KRG_ID), T T INDEX (I_NPR_TILSTAND_ID_NPR)), JOIN (P NATURAL, G INDEX 
(I_ICD10_GRUPPE_ICD10))), I INDEX (PK_ICD10))

D1) ON p.icd10 = t.icd10
S1/D3) ON p.icd10 = substring(t.icd10 from 1 for 3)

These change the plan to:
PLAN JOIN (MERGE (SORT (JOIN (P NATURAL, G INDEX (I_ICD10_GRUPPE_ICD10))), SORT 
(JOIN (T KID INDEX (U_NPR_KRG_ID_FNRK), T N INDEX (I_NPR_KRG_ID), T T INDEX 
(I_NPR_TILSTAND_ID_NPR, I INDEX (PK_ICD10))

The version is Firebird 2.5.1.

I doubt there are much to win by using an index, the ICD10_PURRES p (lookup) 
table contains only 112 rows, each of which contains one integer, one char(4) 
and one char(3) field.

Set


[firebird-support] Why does the optimizer choose NATURAL for this tiny table?

2014-11-12 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Fb 2.5.1

I have an EXECUTE BLOCK statement, for which a small part goes NATURAL where 
I'd expect it to use an index associated with a UNIQUE CONSTRAINT.

I would expect

JOIN icd10_purres p ON p.icd10 IN (t.icd10, substring(t.icd10 from 1 for 3))

to use an index, maybe something along the lines of:

PLAN JOIN (P INDEX(U_ICD10_PURRES_ICD10, U_ICD10_PURRES_ICD10), ...

However, the optimizer goes NATURAL.

ICD10_PURRES is a tiny table, but I thought 112 records might be enough for an 
index to be useful Or is the possibility of reducing the number of potential 
records by 99% not enough to warrant the use of an index? Other tables in the 
query are considerably bigger (NPR contains 7 million, NPR_KRG_ID half a 
million and NPR_TILSTAND 10 million).

This is part of the following FOR SELECT:

  for with tmp (id_npr, avdnr, reshid, icd10, innskrivingsdato, aar, 
omsorgsniva, diagnosenr) as 
(select n.id_npr, n.tjenesteenhetkode, n.tjenesteenhetreshid, 
 iif(substring(t.tilstand from 4 for 1) = '.', substring(t.tilstand from 1 
for 3)||substring(t.tilstand from 5 for 1), substring(t.tilstand from 4 for 1)),
 n.innskrivingsdato, extract(year from n.innskrivingsdato), n.omsorgsniva, 
t.nr
 from npr n
 join npr_krg_id kid on n.npr_krg_id = kid.npr_krg_id
 join npr_tilstand t on n.ID_NPR   = t.ID_NPR
 where kid.fnr_kryptert = :fnr_k
   and not n.innskrivingsdato between current_date-90 and current_date)

select t.id_npr, t.avdnr, t.reshid, t.icd10, t.innskrivingsdato, t.aar, 
p.icd10_c, t.diagnosenr, t.omsorgsniva, g.gruppe, i.beskrivelse
from tmp t
join icd10_purres p on p.icd10 in (t.icd10, substring(t.icd10 from 1 for 3))
join icd10_gruppe g on g.icd10 = p.icd10_c and not exists(select * from 
icd10_gruppe g2 where g2.icd10 = g.icd10 and g.gruppe  g2.gruppe)
left join ICD10 i on t.icd10 = i.kode
into ... do ...

for which the optimizer creates this plan:

PLAN JOIN (JOIN (JOIN (T KID INDEX (U_NPR_KRG_ID_FNRK), T N INDEX 
(I_NPR_KRG_ID), T T INDEX (I_NPR_TILSTAND_ID_NPR)), JOIN (P NATURAL, G INDEX 
(I_ICD10_GRUPPE_ICD10))), I INDEX (PK_ICD10))

Eventually, this EXECUTE BLOCK will be turned into a STORED PROCEDURE. 
Currently, I'm looking at running the procedure maybe half a million times in a 
loop, later it will be run daily or weekly, but then only on a few thousand 
records each time. I haven't tried running things yet, but would expect running 
the EXECUTE BLOCK once to finish quickly, whereas half a million times 
hopefully would take a few hours and not days.

I'm just puzzled and am asking because I would like to increase my 
understanding...

Set


RE: [firebird-support] What is wrong with transactions here?

2014-11-04 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
 Hi!
 
 I have some lines in firebird.log like this:
 ===
 cxv.servers.netTue Nov  4 11:37:38 2014
 Sweep is started by SWEEPER
 Database SkyNetInt
 OIT 1221095, OAT 1231335, OST 1231313, Next 139981575359934
 
 
 cxv.servers.netTue Nov  4 11:37:46 2014
 Sweep is finished
 Database SkyNetInt
 OIT 1248701, OAT 1248707, OST 1248707, Next 1248709
 
 ===

That's housekeeping for transactions. Depending on how applications are 
connect to the database and how the applications are handling 
their connects, statements and commits - you will see a gap between the oldest 
active and the next transaction.

I don't think this can be the reason for next transaction showing 
139981575359934 originally, Marcus - that would require there to be about 1 
million transactions per second for five years of which one of the oldest is 
still active (I would expect this to be more than Firebird can handle and 
certainly more than enough to test the patience of any user of the database).

Though I've no idea what the reason can be and leave this for others to answer,
Set


RE: [firebird-support] update optimization problem

2014-10-29 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi.
in firebird 2.5

Simple descrip tables

table_ud
ud_id   integer not null primary key
field_ud varchar(6)

row count: 383322

table_tmp
ud_id  integer 
cnd    integer 

index (cnd)

row count: 617

UPDATE table_ud ud
SET ud.field_ud = '201401'
WHERE ud.ud_id in (SELECT t.ud_id FROM table_tmp t where t.cnd = 2)

stadistic 
table_ud
read no index: 383322

Why?

This table can grow to millions of rows

How do I optimize it ?

Hi Germán!

Normally, I would use

UPDATE table_ud ud
SET ud.field_ud = '201401'
WHERE EXISTS(SELECT * FROM table_tmp t where ud.ud_id = t.ud_id AND t.cnd = 2)

But I think that Firebird 2.5 have fixed the general problem with 
IN(subselect) already (a common problem with Fb 1.5 was that the subselect 
would be executed for each potential row, but I think that would mean that if 
there were 25 rows with cnd 2, then the count would be 9583050, and not merely 
383322). It could well be that Firebird is still fairly slow on UPDATE queries 
where the only delimiting factor is an EXISTS.

If you want less rows read, I would suggest using

EXECUTE BLOCK AS
DECLARE VARIABLE UDID INTEGER;
BEGIN
  FOR SELECT UD_ID FROM TMP 
  WHERE CND = 2
  INTO :UDID DO
UPDATE TABLE_UD
SET UD.FIELD_UD = '201401'
WHERE UD_ID = :UDID;
END

This ought to reduce your number of reads, but it is of course more tedious to 
write and probably less similar to how it would be done in other databases.

HTH,
Set


Re: [firebird-support] How do I count the number of duplicate rows in a table?

2014-10-28 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Greetings All,

Firebird 1.5.3

Should be elementary but, I'm drawing a blank on how to accomplish this.

I have a table (ACCT_CASE_COURT) that contains these fields (among others):

ACCT_CASE_COURT_IDINTEGERNOT NULLPK
ACCT_IDINTEGERNOT NULL
CASE_IDSMALLINTNOT NULL
CASE_NUMBERVARCHAR(20)NOT NULL
...

How do I form a SQL Select statement that would contain CASE_NUMBER in the 
first column (sorted) and 
number of times that the case number is found in the table in the second 
column (CNT)?

From your description, I'd say the answer is simply

SELECT CASE_NUMBER, COUNT(*) CNT
FROM ACCT_CASE_COURT
GROUP BY CASE_NUMBER

(feel free to add ORDER BY CASE_NUMBER, I didn't since all existing Firebird 
versions happens to do it implicitly when having GROUP BY).

If this is not the answer, then please try to formulate your question 
differently so that we understand what you want.

HTH,
Set

Re: [firebird-support] PSQL: Getting both aggregation and individual rows

2014-10-27 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi!

 I tried this approach before, but it violates my only run GET_DATA
once requirement :-(

Well, with EXECUTE BLOCK and ORDER BY it may be possible to satisfy your MIN 
requirement, but I can't logically understand how it even theoretically wold be 
possible to know the SUM before having gone through all records. Window 
functions in Fb 3 is probably the best answer to your question,  but I'd still 
guess Fb would do two passes under the hood.

Not that I think it matters too much, I assume the first pass to be more costly 
than the second. Have you measured how much more time is required to return the 
entire result set if having the aggregate functions compared to a simpler query 
without them (but with ORDER BY since that makes it more easily comparable)?

Set

On 21.10.2014 21:15, Svein Erling Tysvær
svein.erling.tysv...@kreftregisteret.no [firebird-support] wrote:


 What about

 FOR WITH TMP(MyDateTime, MySum) as
 (SELECT MIN(dateandtime), SUM(Value)
 FROM gen_data(...))
 SELECT g.id, g.name, g.dateandtime, g.value, t.MyDateTime, tMySum
 FROM gen_data(...) g
 CROSS JOIN tmp t

 Of course, you may want a different join to CROSS JOIN.

 HTH,
 Set


Re: [firebird-support] VarChars sometimes begin with single or double quote

2014-10-27 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I've not been able to find any topic that comes close to addressing my 
question, and it seems so basic, I'm guessing that I'm missing something 
fundamental.

I have queries that specify for ranges in varchar fields and return those and 
populate my VirtualStrings in a standard alphabetical grouping.

The database I work with has some strings / varchar fields _begin_ with a 
_single_ or a _double_ quote, for emphasis or for identifying a literary work, 
etc., 
for output in components where there is not an italic feature.

Using the standard = or = works fine for varchar fields that begin with 
numbers and letters, but skips over those which begin with ''' single-quote 
or '' double-quote.

Is there some schema which I could have followed to find my way to the a nswer 
to this conundrum of mine?

Ideally, I would prefer to have the varchar fields which begin with a 
single-quote or a double-quote collated in the proper order according to the 
first letter, 
regardless of upper or lowercase, or presence or lack of single- or 
double-quote.

No, Barry, this is not fundamental to a database (I would admit that it could 
be considered fundamental to a programming language). I would recommend you to 
create an auto-generated proxy column and use this for your sorting (whether or 
not you include it in your result set). E.g. something like:

CREATE TABLE TEST_SORTING 
(
  PKINTEGER NOT NULL,
  MYSTRING  VARCHAR(50) CHARACTER SET ISO8859_1,
  STRIPPED  VARCHAR(50) CHARACTER SET ISO8859_1,
 CONSTRAINT PK_TEST_SORTING PRIMARY KEY (PK)
);

SET TERM ^^ ;
CREATE TRIGGER TEST_SORTING_UCQ FOR TEST_SORTING ACTIVE BEFORE INSERT OR UPDATE 
POSITION 0 AS
declare variable s  varchar(50);
declare variable US varchar(50);
begin
  if (new.MyString  '') then
  begin
us = '';
s = upper(new.MyString);
while (s  '') do
begin
  if (substring(s from 1 for 1) not in (, '')) then
us = us || substring(s from 1 for 1);
  s = substring(s from 2 for character_length(s)); 
end
new.stripped = us;
  end
end ^^
SET TERM ; ^^

HTH,
Set

Re: [firebird-support] PSQL: Getting both aggregation and individual rows

2014-10-21 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
What about

FOR WITH TMP(MyDateTime, MySum) as
(SELECT MIN(dateandtime), SUM(Value)
 FROM gen_data(...))
SELECT g.id, g.name, g.dateandtime, g.value, t.MyDateTime, tMySum
FROM gen_data(...) g
CROSS JOIN tmp t

Of course, you may want a different join to CROSS JOIN.

HTH,
Set

Fra: firebird-support@yahoogroups.com [firebird-support@yahoogroups.com]
Sendt: 21. oktober 2014 09:39
Til: Firebird Support
Emne: [firebird-support] PSQL: Getting both aggregation and individual rows

Hi!

Is there a simple way to get an aggregation of some query as well as the
individual rows from within a PSQL? I.e., I have a stored procedure
GEN_DATA which produces individual rows (ID, Name, DateAndTime, Value).
I am processing the output of GEN_DATA in another stored procedure
PROCESS_DATA:

  FOR SELECT id, name, dateandtime, value
  FROM gen_data(...)
  INTO ...
  DO ...

Within this loop, I need the individual records, but I also need some
aggregations on them, i.e. MIN(dateandtime) or SUM(value). If I could
run GEN_DATA twice, then it would be easy (in the first run I would
calculate the aggregations, in the second run the individual values),
but I can't. If I could perform the processing in my application (rather
than the stored procedure), it would be easy, too (I would simply
traverse the result dataset of GEN_DATA twice), but again I can't do
that. Would Common Table Expressions or perhaps Derived Tables help me?

Thanks,

Josef

RE: [firebird-support] Request new feature - better perfomance

2014-10-20 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Maybe I was not clear as I should be but here is an example in Firebird:

select something,anotherthing,(select sum(thirdthing) from second b where 
b.something = a.something) total from a where 
(select sum(thirdthing) from second b where b.something = a.something)  10
 
tray sentence:
select a.someting, a.anotherthing, b.total
from first a inner join (
select someting,sum(thirdhing) as total
from second group by someting ) b on a.someting=b.someting
where b.total10

Other alternatives (though I guess whether or not the performance is acceptable 
will depend on table content):

a)
select something, anotherthing, 
   (select sum(thirdthing) from second b where b.something = a.something 
having sum(thirdthing)  10) total 
from a

b)
with tmp(something, total) as
(select something, sum(thirdthing)
 from b 
 group by 1
 having sum(thirdthing)  10)
select a.someting, a.anotherthing, b.total
from a
join tmp on a.something = tmp.something

c)
execute block returns(something integer, anotherthing varchar(5) collate 
whatever, Total integer) as
begin
  for select a.something, a.anotherthing, sum(b.thirdthing)
  from a 
  join b on a.something = b.something
  group by 1, 2
  into :Something, :AnotherThing, :Total do
  begin
if (Total  10) then Suspend;
  end
end

d)
select a.something, a.anotherthing, sum(b.thirdthing) Total
from a 
join b on a.something = b.something
group by 1, 2
having sum(b.thirdthing)  10


The result of a) differs from the others in that it will return a line (with 
Total = NULL if sum  10) for all rows of a. b) should return identical results 
to your original query, whereas I think c) and d) will double the result of 
Total if there are two occurrences of a.something (triple if three, quadrouple 
if four etc).

in Oracle it looks like
 
select something,anotherthing,(select sum(thirdthing) from second b where 
b.something = a.something) total from a where 
total 10
 
and subquery executed only once but in Firebird subquery is executed twice. 
When you have very complex subquery and possible two or three times 
using total value in where clause it makes great impact on perfomance and of 
course it is very bad query but in Oracle it works like charm.

Don't know Oracle, but I admit that it is sometimes beneficial to tweak the SQL 
statement in Firebird to improve performance. I neither know whether or not it 
would feasible or if it would improve performance to allow the syntax you 
suggest, I think Dmitry (or similar) once wrote on this list that whilst being 
duplicate in terms of syntax and plan, it added almost nothing to the execution 
time since things would already be in the cache.

As for the syntax, I'm not used to the result of a subselect being available in 
the where clause (it would take me a bit of time to get accustomed to results 
of subselects being available in the where clause, but not the result of 
aggregate functions not in a subselect), but I may agree that it could make 
large statements more easily readable.

HTH,
Set


RE: [firebird-support] How do I return an accurate COUNT(*) when a JOIN is involved?

2014-10-14 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
ACCT_CASE: Case Management table
ACCT_IDINTEGER    NOT NULL    PK
CASE_ID    SMALLINT    NOT NULL    PK
CLT_ID    INTEGER    NOT NULL    FK to CLIENT table   Need this for the JOIN
 
DEBTOR_CASE_DEBT:  Allows for multiple PERSON's to be associated with a DEBT
ACCT_IDINTEGER    NOT NULL    PK
CASE_ID    SMALLINT    NOT NULL    PK
DEBT_NO    SMALLINT    NOT NULL    PK
PERSON_ID    INTEGER    NOT NULL    PK
STATUS_DATE    TIMESTAMP    NOT NULL
STATUS_CODE    CHAR(1)    NOT NULL
 
What am I attempting to do?  I need to know how many records are in the 
DEBTOR_CASE_DEBT table that have a STATUS_DATE between '09/01/14' and 
'09/30/14' 
and the STATUS_CODE = 'B (Bankruptcy Filed) and is for a specific CLT_ID 
(thus the join to ACCT_CASE to use CLT_ID).  I do not want to include the 
PERSON_ID when fetching a COUNT() of the record, I only need to know how many 
debts are in this status for the client.  So only concerned with ACCT_ID, 
CASE_ID and DEBT_NO.
 
So this SQL will return the correct number of records, now I just have to 
figure out how to return a count in one record.
 
  SELECT DISTINCT DCD.ACCT_ID, DCD.CASE_ID, DCD.DEBT_NO
 FROM DEBTOR_CASE_DEBT DCD
 JOIN ACCT_CASE AC ON AC.ACCT_ID = DCD.ACCT_ID
  AND AC.CASE_ID = DCD.CASE_ID
    WHERE DCD.STATUS_DATE BETWEEN :V_BEGIN_DATE AND :V_END_DATE
  AND DCD.STATUS_CODE = 'B'
  AND AC.CLT_ID = :V_CLT_ID

Did I provide enough information this time?  If not feel free to ask...

This is close to a perfect problem description, Mike, well done! The only 
(minor) thing lacking is a reason for you not wanting CLT_ID included...

I can think of two possible solutions:

a)
  SELECT COUNT(DISTINCT DCD.ACCT_ID||'-'||DCD.CASE_ID||'-'||DCD.DEBT_NO)
  FROM DEBTOR_CASE_DEBT DCD
  JOIN ACCT_CASE AC ON AC.ACCT_ID = DCD.ACCT_ID
   AND AC.CASE_ID = DCD.CASE_ID
  WHERE DCD.STATUS_DATE BETWEEN :V_BEGIN_DATE AND :V_END_DATE
AND DCD.STATUS_CODE = 'B'
AND AC.CLT_ID = :V_CLT_ID

b)
  SELECT COUNT(*)
  FROM DEBTOR_CASE_DEBT DCD
  WHERE DCD.STATUS_DATE BETWEEN :V_BEGIN_DATE AND :V_END_DATE
AND DCD.STATUS_CODE = 'B'
AND EXISTS(SELECT * FROM ACCT_CASE AC 
   WHERE AC.ACCT_ID = DCD.ACCT_ID
 AND AC.CASE_ID = DCD.CASE_ID
 AND AC.CLT_ID = :V_CLT_ID)

Myself, I generally prefer to have single field primary keys, one benefit of 
this is that you can use solution a) without having to do tricks with 
concatenation.

HTH,
Set


RE: [firebird-support] BLOB

2014-10-13 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Text, binary, it's all the same to gbak.   Try the -g suggestion - if gbak is 
cleaning out garbage, it's slow.

But, surely, the garbage has to be cleaned out sooner or later, and doing it 
in a backup run is the cheapest way to do it, 
as every record is being visited anyway? (Compared to, say, doing a COUNT(*) 
to clean garbage, which will visit records it 
doesn't need to, or, worst of all, letting the cost land at random on 
whichever poor sod next does a query on the table 
with the garbage.)

Hi Tim!

The original question was:

Why does it takes so much time to backup / restore (gbak) this table ? 
(because the BLOB field). 
Do I have any options to speed up the process ?

If the original database should not be replaced by the restored version, then 
it is of course sensible to clear garbage. However, I suggested trying this 
switch since this could be an alternative way to discover whether the problem 
was (mainly) related to poor transaction handling and not the blob itself.

I'm actually surprised that Tiberiu notices a problem at all, a table 
containing 3000 rows and blobs of up to 400 characters should be peanuts for 
Firebird.

Set


[firebird-support] Re: Simultaneous inserts / selects

2014-10-10 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
All values for inserts are converted to string so there are no parameters.

Sorry to hear that.

MyStatement.SQL.Text:=’INSERT INTO MyTable(Field1, Field2) VALUES (:Param1, 
:Param2)’;
MyStatement.Prepare;
while not eof(InputFile) do
begin
  readln(InputFile);
  MyStatement.Params[0].AsInteger:=IntegerFromFile;
  MyStatement.Params[1].AsString:=StringFromFile;
  MyStatement.Execute;
end
MyTransaction.Commit;

is magnitudes faster (5 000 records per second could be feasible) than

while not eof(InputFile) do
begin
  readln(InputFile, s);
  MyStatement.SQL.Text:=s;
  MyStatement.Prepare;
  MyStatement.Execute;
end
MyTransaction.Commit;

I only know of two ways to go if you want decent performance for largish 
inserts, one is to use external tables (I’ve never used them, but I trust they 
are the quickest way), the other statements that you prepare before the loop 
and use with parameters.

Sorry,
Set


Re: [firebird-support] DATEDIFF(HOUR...) returns 1 for a 45 minutes interval

2014-10-04 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi all

I would have attached a screen shot of the sample data but I guess that is not 
possible.  What I am trying to achieve right now is get the time difference in 
hh:mm format to the user

tStartTime and tEndTime field values

26.08.2014, 08:38:00.00026.08.2014, 09:45:00.000
26.08.2014, 10:00:00.00026.08.2014, 10:45:00.000
26.08.2014, 11:00:00.00026.08.2014, 12:00:00.000
26.08.2014, 11:30:00.00026.08.2014, 12:15:00.000
26.08.2014, 00:15:00.00026.08.2014, 13:30:00.000

and the following is the query

SELECT sProdLineWorkProcess.*, (DATEDIFF(HOUR, 
sProdLineWorkProcess.tStartTime, sProdLineWorkProcess.tEndTime)) AS 
nHoursWorked
, (DATEDIFF(MINUTE, sProdLineWorkProcess.tStartTime, 
 sProdLineWorkProcess.tEndTime) - (DATEDIFF(HOUR, 
 sProdLineWorkProcess.tStartTime, sProdLineWorkProcess.tEndTime) * 60)) AS 
 nHoursWorked
, (DATEDIFF(MINUTE, sProdLineWorkProcess.tStartTime, 
 sProdLineWorkProcess.tEndTime)) AS nTotalMinutesWorked
FROM sProdLineWorkProcess
JOIN tProdLineWork
ON tProdLineWork.iID = sProdLineWorkProcess.iPID
WHERE CAST(tProdLineWork.tDt AS DATE) = '2014-08-26'
--GROUP BY sProdLineWorkProcess.iEmployeeID

The calculated field values are as follows:

1767
04545
1060
1-1545
1315795

Please see the 4th row, the diff between 11:30 and 12:15 is 1 Hour and -15 
mins whereas difference between 10:00 and 10:45 is 0 hour and 45 mins.

Please advise on what I need to do correctly to get 0 hour and 45 mins for 
both 2nd and 4th row.

If you only care about hours and minutes, then your attempt is pretty close to 
one possible solution, Bhavbhuti. Try something similar to (assuming 
sProdLineWorkProcess has a unique ID field):

with tmp(ID, nHours, nMinutes) as
(SELECT plwp.ID, DATEDIFF(HOUR, plwp.tStartTime, plwp.tEndTime),
DATEDIFF(MINUTE, plwp.tStartTime, plwp.tEndTime) - (DATEDIFF(HOUR, 
plwp.tStartTime, plwp.tEndTime) * 60)
 FROM sProdLineWorkProcess plwp
 JOIN tProdLineWork plw
   ON plw.iID = plwp.iPID
 WHERE CAST(tProdLineWork.tDt AS DATE) = '2014-08-26')

select plwp.*, iif(nMinutes  0, nHours - 1, nHours) nHoursWorked,
   iif(nMinutes  0, nMinutes + 60, nMinutes) nMinutesWorked
from tmp
join sProdLineWorkProcess plwp on tmp.ID = plwp.ID

HTH,
Set

Re: [firebird-support] How to improve Firebird 2.5.3 Disk I/O on Windows server 2012 R2

2014-09-29 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Obviously the logic of my application is not the best, but it needs to pass
through a special interface, that transforms classic cobol read/write
routines, in sql statements. This brings to the need to  have a single
commit after a single insert command of a single record. I know this is not
good, but knowing this and knowing that I cannot change this, I only want to
know if I can get the best for my Firebird Installation of 2.5.3 SuperServer
onto Windows Server 2012 R2 x64.

OK, commit after every single insert will slow things down considerably and may 
be the reason for your time trouble (it is similar to having trouble with a car 
being slower than a bike, and the reason being that you have an additional 
requirement to start and stop every 5 meters). I'm not certain (because I've 
never had a similar requirement and know very little about CommitRetaining), 
but maybe changing from Commit to CommitRetaining might make it possible for a 
prepared statement to survive the CommitRetaining (?) and then only do a proper 
Commit occationally. It could at least be worth a try if feasible.

I'm trying several settings, some others have suggested in this thread.

About your test (thanks for that), I have created the table, than copied and
pasted the SQL loop, but I get this error:

Preparing statement: execute block returns (i integer) as
declare variable i2 integer
Error: *** IBPP::SQLException ***
Context: Statement::Prepare( execute block returns (i integer) as
declare variable i2 integer )
Unexpected end of command - line 2, column 21

This is probably due to IBPP believing the ; to be the end of the statement. 
Try to 'SET TERM ^^ ;' before execute block, change the final end of the 
execute block to end^^ and then do 'SET TERM ; ^^' at the end.

Sorry for not being able to help more,
Set

Re: [firebird-support] How to improve Firebird 2.5.3 Disk I/O on Windows server 2012 R2

2014-09-28 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi Sean, thanks for the contribution.

Some answers to your requests:

1)  Logic of application.

It is a Microfocus Cobol legacy application, with latest (2014) x64 runtime. 
The long time is obviously not relative to a simple sql command, but to the 
overall execution. 
We have developed a dedicated interface (a Delphi x64 service and dll), cobol 
uses to read from vision indexed cobol files, read into Firebird table if 
record exist and than 
insert the record. It is to populate new tables, in order to use a different 
application with firebird database. The same application runs on windows 
server 2003 32bit, 
windows server 2008 64 and SLES 11 SP1 x64. The interface and dll’s are the 
same, just like the cobol program.

The problem is related to the fact that I expected a real big difference 
between old or very old hardware in RAID 1 configuration, and this brand new 
hardware, instead 
it gained only 20/30 %. Consider this: another application, that runs only in 
cobol environment, without database, has passed from 2 hrs to 15 minutes !!

Just to say, that surely we can improve our legacy application or the Delphi 
interface. But if I compare the identical application, with very different 
machines, I see a 
little improvement dispite the big difference in hardware (Firebird is always 
2.5)

I'm not surprised, I think Firebird SuperServer will only use one core.

I created a table:

CREATE TABLE TEST 
(
  ID INTEGER NOT NULL,
  MYINT  INTEGER,
  CONSTRAINT PK_TEST PRIMARY KEY (ID) --for this test an important primary key
);

Then I executed the following query on the empty table:

execute block returns (i integer) as
declare variable i2 integer;
begin
  i = 0;
  i2 = 0;
  while (i  100) do
  begin
i = i+1;
i2 = i2+i;
while (i2  10) do
  i2 = i2 - 1;
update or insert into test(id, myint)
values (:i2, :i);
  end
  suspend;  
end

16.5 seconds later the query had looped and inserted or updated 1 millon times, 
4 rows where inserted, the rest of the times things were updated. Maybe you 
should add half a second for the commit afterwards. This on a computer that is 
a few years old and nothing special. The database is Firebird 2.5, don't 
remember whether it is 2.5.1 or 2.5.2.

Now, this is very different from your import from a text file. Still, I hope it 
is enough to show that 9 minutes to check and insert 35000 records is more than 
what is normally neccessary. You could either continue to try to improve the 
environment and maybe get the import to finish within 5 or 7 minutes after some 
further optimization. Or you could try to discover and fix the real problem 
through telling us more about what is actually going on (what does your SQL 
look like, what PLANs are used, which indexes are used, do you use prepared 
statements or create 35000 separate statements and how many transactions?) and 
hopefully get the import to finish in less than one minute.

HTH,
Set





++

Visit http://www.firebirdsql.org and click the Documentation item
on the main (top) menu.  Try FAQ and other links from the left-side menu there.

Also search the knowledgebases at http://www.ibphoenix.com/resources/documents/ 

++


Yahoo Groups Links

* To visit your group on the web, go to:
http://groups.yahoo.com/group/firebird-support/

* Your email settings:
Individual Email | Traditional

* To change settings online go to:
http://groups.yahoo.com/group/firebird-support/join
(Yahoo! ID required)

* To change settings via email:
firebird-support-dig...@yahoogroups.com 
firebird-support-fullfeatu...@yahoogroups.com

* To unsubscribe from this group, send an email to:
firebird-support-unsubscr...@yahoogroups.com

* Your use of Yahoo Groups is subject to:
https://info.yahoo.com/legal/us/yahoo/utos/terms/



[firebird-support] RE: Firebirdsql adding new charsets to database

2014-09-16 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
If your database has the right ODS version, i.e. that it is created with 
Firebird 2.5, then you can just use the character set – i.e.

CREATE TABLE MyTable(
  MyChineseField Varchar(50) character set GB18030,
  MyNorwegianField Varchar(50) character set iso8859_1 collate no_no,
  MyASCIIField Varchar(50) character set ASCII);

I’ve never used it myself, but a quick search on the Internet indicates that 
FBClone possibly could help you change the character set of an existing 
database.

HTH,
Set

From: firebird-support@yahoogroups.com [mailto:firebird-support@yahoogroups.com]
Sent: 16. september 2014 00:07
To: firebird-support@yahoogroups.com
Subject: [firebird-support] Firebirdsql adding new charsets to database




Dear Firebirdsql Community,
I want to add GB18030 charset to an existing firebirdsql database. How can I do 
that? Is that even doable, or will that require a new database to be created?

Firebird database engine version: 2.5.2

Thank you!


Regards,
Vardan Minasyan


Regards,
Vardan Minasyan
949-645-1019 x2

If you need to send us a file, follow the link below.
https://quickbooksconsultant.sharefile.com/r/r487ddfe0d9c490f8







[Non-text portions of this message have been removed]



Re: [firebird-support] Select based upon date between two date fields

2014-09-15 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
 The sql is below. It works fine until I add the BETWEEN statement. Hopefully
 you can point out something simple that I am doing wrong.


 SELECT description, WOReqd, Addontype as AddonTypeID, RatebookID FROM
 rentaladdons LEFT JOIN rentalratebook on rentaladdons.ratebookID =
 rentalratebook.ratebookID WHERE addonID = '1002' and cast('09/15/2014' as
 date) BETWEEN rentalratebook.fromdatetime and
 rentalratebook.todatetime

You are using the wrong approach, you need to try:

SELECT
  description, WOReqd, Addontype as AddonTypeID, RatebookID
FROM rentaladdons
  LEFT JOIN rentalratebook on rentaladdons.ratebookID 
 =rentalratebook.ratebookID
WHERE
  addonID = '1002'
  and rentalratebook.fromdatetime = cast('09/15/2014' as date)
  and rentalratebook.todatetime = cast('09/15/2014' as date)

Why is his approach wrong, Sean? It might be unusual to have the constant on 
the left side of a comparison, but I'm sure I've done it when it is the easiest 
way to write a query. I'm pretty sure date BETWEEN date AND date should 
work regardless of which dates are constant, parameters or field names.

I think his error has nothing to do with the BETWEEN, but rather the reason is 
that he didn't only add the BETWEEN, he also added the LEFT JOIN and at least 
RatebookID exists in both tables (probably giving him the ambiguous field name 
error). He may just have assumed it was the BETWEEN that gave him the error, 
rather than try the statement without the BETWEEN.

I'd change the query to:

SELECT ra.description, ra.WOReqd, ra.Addontype as AddonTypeID, ra.RatebookID 
FROM rentaladdons ra
JOIN rentalratebook rr on ra.ratebookID = rr.ratebookID 
WHERE ra.addonID = '1002' AND '09/15/2014' BETWEEN rr.fromdatetime and 
rr.todatetime

(change ra to rr if I guess wrong which table some fields belong to)

LEFT JOIN is sometimes good to use, but in your case you use fields from 
rentalratebook also in your WHERE clause, effectively turning the LEFT JOIN 
into an [INNER] JOIN. [INNER] JOIN gives the optimizer more of a choice 
regarding which PLAN to generate, so in this query, you're probably better off 
not using LEFT (LEFT JOINs can sometimes be useful, but this is not one of 
those cases). Moreover, there's no need to cast 09/15/2014 to date, it doesn't 
harm doing it, but you don't need to.

One further thing to note, is that you use date between datetime and 
datetime. 09/15/2014 is between 09/14/2014 00:00:01 and 09/15/2014 23:59:59, 
but it is not between 09/15/2014 00:00:01 and 09/15/2014 23:59:59. Moreover, I 
would not trust that it was between 09/15/2014 00:00:00 and 09/15/2014 
23:59:59, since I would be uncertain whether 09/15/2014 00:00:00 was an exact 
value or an approximation that could be slightly less or slightly more than 
09/15/2014.

HTH,
Set

Re: [firebird-support] SQL Error -104

2014-09-13 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
i just don't get it what the heck i'm doing wrong. I would like to have
something like that:

select ba.artno
from mov_invoices mi, bas_articles ba
where mi.invdate between '2014-05-01 00:00:00' and '2014-08-01 00:00:00'
and case
when (ba.artno like '90__') then '9000'
when (ba.artno like '80__') then '8000'
when (ba.artno like '70__') then '7000'
when (ba.artno like '60__') then '6000'
when (ba.artno like '50__') then '5000'
when (ba.artno like '40__') then '4000'
when (ba.artno like '30__') then '3000'
when (ba.artno like '20__') then '2000'
when (ba.artno like '10__') then '1000'
end

any ideas somebody?

The reason this fails, Johannes, is that all parts a the WHERE clause should 
evaluate to a Boolean value and your query doesn't.

mi.invdate between '2014-05-01 00:00:00' and '2014-08-01 00:00:00' will 
evaluate to true or false (or null), but you have no equality, between or 
similar for your case statement (you have only specified one side of the 
comparison - it's the same as specifying mi.invdate and forgetting between and 
the dates).

Also, there's no need for you to use CASE in your case. Try something like:

select ba.artno
from bas_articles ba
join mov_invoices mi on substring(ba.artno from 1 for 2) || '00' = 
mi.something
where mi.invdate between '2014-05-01 00:00:00' and '2014-08-01 00:00:00'

I'm guessing that your case statement creates a value that should be compared 
to a value in mov_invoices, and that you do not want to return articles not 
related to the invoice. If I'm wrong, replace JOIN with CROSS JOIN, remove the 
ON part and move the substring to the WHERE clause.

HTH,
Set

SV: [firebird-support] Firebird Embedded corruptions

2014-09-13 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi,

We have shipped Firebird Embedded bundled together with our product for a few 
years now and the system is currently in production at several thousand of our 
customer's sites. 
Currently we are using Firebird Embedded 2.5.1 with the latest .NET-driver and 
a stack consisting of Castle Active Record on top on NHibernate and the system 
is running on the 
latest versions of Windows.

All is well and Firebird has served us good so far with the exception of 
database corruptions that gets reported from a new set of customers every 
week. For some of them it is 
possible to instruct the customer on how to repair the databases themselves, 
but some of the databases are unfortunately so heavily corrupted that they 
need to be sent to us 
for repairing (which is a tedious work that steals time from other tasks). 
Most of them corruptions are normally found in the tables that gets the most 
writes, but I guess that is 
only natural.

We are now at the planning stage for the next major release of our product and 
we are thus rethinking if Firebird really is a good choice, because of this.

Lots of effort has gone into solving this problem on our side, so I think the 
normal prerequisites has already been put into place (e.g using forced writes 
and so forth), but our 
system needs to be up and running 24x7, which means that it is not possible to 
schedule periodic backup/restore cycles and my personal theory is that 
Firebird embedded gets 
corrupted over time if you are not doing this regularly.

So I have have a few questions that I would appreciate if someone could answer:

1. Is it feasible to run Firebird Embedded 24x7 in a setup where there are no 
scheduled backup/restore cycles. If not, how often should this be performed to 
ensure that the 
database does not get corrupted.

2. Most of our customers are not using a UPS. From my experiments I have not 
managed to create a corrupted database by turning of the power while doing a 
large set of 
writes (in a session running in VirtualBox). Could someone please confirm that 
this is indeed safe when you are running with synchronized writes turned on?

3. Are there any operations on a live database that should be avoided to 
minimize the risk of corruptions?

4. Just read a discussion about whether it is needed or not to call 
fb_shutdown to stop Firebird Embedded. Could this be the reason why we are 
getting corruptions? Should 
we change our service to perform this call when it is stopped?

5. I have also seen discussions of turning of automatic sweeps of the database 
(and doing them manually instead). Is this a likely source of corruptions for 
our setup?

Thanks in advance. Maybe are there no certain answers to my questions, but any 
pointers in the right direction would be very appreciated. Firebird has been a 
real workhorse 
for us and we would rather like to keep it.

Hei Jan!

The one thing I try to avoid, is running DDL (CREATE, ALTER, DROP 
table|trigger|stored procedure) on a database in use. Maybe I'm overly 
careful, but not all too long ago, a colleague caused some problems when he did

ALTER MyTable DROP MyField;

while he simultaneously had another transaction having uncommitted changes to 
MyField in one record.

I think (but have no experience), that possible reasons for corruption could 
include file system backups of the database while it is in use (exclude the 
database file(s) from such backups, rather use gbak for the backup, and include 
the resulting file in the system backup), and possibly anti-viruses preventing 
Firebird from doing it's work (though I would expect this to result in the 
database being unaccessible, not corrupted).

Another thing that's only affecting Fb 2.5.1, is that this version has an error 
relating to compund indices (requiring backup/restore or rebuilding such 
indices if upgrading to 2.5.2). Though I doubt this error would cause data 
corruptions involving more than the index.

Others will be able to give you a more thorough answer, despite having used 
Firebird since it's inception (0.9.4), I've very little experience with 
corruptions (undoubtedly related to only working on a handful of databases with 
about 20 simultaneous users).

HTH,
Set

Re: [firebird-support] How merge two queries

2014-09-10 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hallo,
   I have two queries:

First (results: ANNO, IMPONIBILE):
select
   EXTRACT(YEAR FROM DT.DATA_DOCUMENTO) AS ANNO,
   SUM(DC.IMPORTO) AS IMPONIBILE
from
   DOC_CORPO DC,
   DOC_TESTA DT,
   VOCI V
WHERE
   DT.ID = DOC_TESTA_ID
   AND DT.DOCUMENTO_ID  'PRO'
   AND EXTRACT(YEAR FROM DT.DATA_DOCUMENTO) = 2013
   AND DC.VOCE_ID = V.ID
   AND V.CONTRIBUTI = 1
GROUP BY EXTRACT(YEAR FROM DT.DATA_DOCUMENTO)

Second (results: ANNO, IMPOSTA):
select
   EXTRACT(YEAR FROM DT.DATA_DOCUMENTO) AS ANNO,
   SUM(DC.IMPORTO) AS IMPOSTA
from
   DOC_CORPO DC,
   DOC_TESTA DT
WHERE
   DT.ID = DOC_TESTA_ID
   AND DT.DOCUMENTO_ID  'PRO'
   AND EXTRACT(YEAR FROM DT.DATA_DOCUMENTO) = 2013
   AND DC.VOCE_ID = 'ENPACL'
GROUP BY EXTRACT(YEAR FROM DT.DATA_DOCUMENTO)

There is a way to merge those two queries to obtain the same result in
one query that results: ANNO, IMPONIBILE, IMPOSTA?

Hi, Luigi!

You could try something like (I'm assuming that DOC_TESTA_ID belongs to DC and 
that ID is the primary key of VOCI):

select
   EXTRACT(YEAR FROM DT.DATA_DOCUMENTO) AS ANNO,
   SUM(IIF(V.ID is not null, DC.IMPORTO, null)) AS IMPONIBILE, --sum only those 
that are in V
   SUM(IIF(DC.VOCE_ID = 'ENPACL', DC.IMPORTO, null)) AS IMPOSTA --sum only 
those that have correct DC.VOCE_ID
from DOC_CORPO DC
join DOC_TESTA DT on DC.DOC_TESTA_ID = DT.ID
left join VOCI V on DC.VOCE_ID = V.ID and V.CONTRIBUTI = 1 --assuming 0 or 1 
match
where DT.DOCUMENTO_ID  'PRO'
  and DT.DATA_DOCUMENTO between '2013-01-01' and '2013-12-31' --BETWEEN can use 
an index, EXTRACT cannot
  and (DC.VOCE_ID = 'ENPACL' or V.ID is not null) --to avoid all rows that 
doesn't fit either of the requirements
group by EXTRACT(YEAR FROM DT.DATA_DOCUMENTO)

HTH,
Set

[firebird-support] Re: Insert ot update statements locks a table and all other instances that try to run same statement are lcoked to

2014-09-06 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
CASHBOXID is already know. It is a reference to a table that we don't touch in 
the transaction.
This table contains the current total amount of a cash box at the begging of 
the day.
So when I try to load data for a cash box a java code checks is there record 
for this cash box for current day. 
If there is no such record it calculates the total current amount and calls 
the insert that adds a record to this table.

Usually inserting record with same value for primary key will create error and 
probably will not  block the execution of the statement.
User is sysdba. There is no security restrictions for access to database.
End users have no access to database server at all. They all use code that 
runs in application server to access or modify data. 
That is why I'm not restricting the access to the database for the moment.

I'm not sure it is a lock conflict. But I suspect that something is locked 
somewhere and that forces the execution of the 
statement to stop and to lock all other inserts that other connections try to 
execute.

As I said I need ideas or hints what to do in order to find the real problem 
when this situation happens again.
One more thing. When I try to stop application server when this happens all 
connections that are blocked including the initial one stop the shutdown of 
the server.
When I try to kill firebird process that initially blocked the execution all 
other processes are unlocked and server is shutdown after that.
But in this case I try guess which process is that. When I look in the 
monitoring tables I can't see the pid of the process of each statement.

Have you considered trying something like (written using a text editor, so 
there could well be errors):

CREATE GENERATOR PK_GEN;
CREATE TABLE CASH_CASHBOX_DAY_AMMOUNT 
( PK INTEGER NOT NULL,
  CASHBOXID  INTEGER NOT NULL,
  DATE_TIME  NUMERIC( 18, 0) NOT NULL,
  AMMOUNTNUMERIC( 18, 0),
 CONSTRAINT PK_CASH_CASHBOX_DAY_AMMOUNT PRIMARY KEY (PK)
);
ALTER TABLE CASH_CASHBOX_DAY_AMMOUNT ADD CONSTRAINT FK_CASH_CASHBOX_DAY_AMMOUNT 
  FOREIGN KEY (CASHBOXID) REFERENCES CASH_CASHBOX
  (ID);

CREATE INDEX IDX_CCDA_CASHBOXID ON CASH_CASHBOX_DAY_AMMOUNT(CASHBOXID);
CREATE INDEX IDX_CCDA_DATE_TIME ON CASH_CASHBOX_DAY_AMMOUNT(DATE_TIME);

SET TERM ^^ ;
CREATE TRIGGER CASH_CASHBOX_DAY_AMMOUNT_PK ACTIVE BEFORE INSERT AS
BEGIN
  if (new.PK IS NULL) then
new.PK = GEN_ID(PK_GEN, 1);
END ^^

SET TERM ; ^^

If this makes the problem disappear for INSERTs, then that problem is you 
inserting identical CASHBOXID and DATE_TIME combinations.

If this is the problem, you'd probably want to change a few selects in your 
programs from (e.g.)

select cashboxid, date_time, ammount
from cash_cashbox_day_ammount

to

select cashboxid, date_time, sum(ammount) ammount
from cash_cashbox_day_ammount
group by 1, 2

since there now can be duplicates.

Another thing is that you now may want to do some occational housekeeping, 
allowing for duplicates to occur is not the same as wanting there to remain 
duplicates of CASHBOXID and DATE_TIME over time in your database. I'd recommend 
you to run this statement regularly, e.g. once each night or week (change it to 
a stored procedure if you want to - and if this table is huge, you may want to 
add another trigger-populated field with the insert and update time - so that 
you can exclude rows not changed/inserted recently from the calculation):

execute block as
declare variable cbid integer;
declare variable dt   numeric(18,0);
declare variable total_amount numberic(18,0);
begin
  for select cashboxid, date_time, sum(ammount)
  from cash_cashbox_day_ammount
  group by 1, 2
  having count(*)  1
  into :cbid, :dt, :total_amount do
  begin
delete from cash_cashbox_day_ammount
where cashbox_id = :cbid
  and date_time = :dt;
insert into cash_cashbox_day_ammount(cashboxid, date_time, ammount)
values(:cbid, :dt, :total_amount);
  end
end

HTH,
Set

RE: [firebird-support] Insert ot update statements locks a table and all other instances that try to run same statement are lcoked to

2014-09-05 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
This is the definition of the table that locks on insert:

CREATE TABLE CASH_CASHBOX_DAY_AMMOUNT
(
  CASHBOXID  INTEGER NOT NULL,
  DATE_TIME  NUMERIC( 18, 0) NOT NULL,
  AMMOUNTNUMERIC( 18, 0),
 CONSTRAINT PK_CASH_CASHBOX_DAY_AMMOUNT PRIMARY KEY (CASHBOXID, DATE_TIME)
);
ALTER TABLE CASH_CASHBOX_DAY_AMMOUNT ADD CONSTRAINT FK_CASH_CASHBOX_DAY_AMMOUNT
  FOREIGN KEY (CASHBOXID) REFERENCES CASH_CASHBOX (ID);

It is simple insert that just inserts single record. There is no triggers or 
generators. Primary key value is know before insert is executed.

I see two likely ways an insert can fail here:


1)  The CASHBOXID doesn’t exist or has been inserted in another transaction 
that is not yet committed

(possible solution: insert into CASH_CASHBOX and CASH_CASHBOX_DAY_AMMOUNT in 
the same transaction)

2)  A record with the same CASHBOXID and DATE_TIME already exists

Can be avoided by using a new field populated through a generator as the 
primary key – but you would then probably have to also implement a ‘duplicate 
resolution’-button or similar in your program to fix up those cases where there 
are several records with the same CASHBOXID and DATE_TIME

Either of these ought to give you an error message (which would be good to post 
on this list).

Your problem could of course be related to something completely different (like 
Mark suggests – or something stupid like the user having no insert rights to 
the table), but if it is the inserts themselves that are the problem, I see no 
other possible reason for a lock conflict.

Set


[firebird-support] RE: Case insensitive search on a memo field

2014-09-05 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi,
I'm using Firebird 2.5.3, and I am looking for text in a memo field, eg.

I take it you mean BLOB or VARCHAR, I've never heard of memo fields in Firebird?

Select * from mytable t where t.mymemo like '%find me%'
The will only find
find me
and not
FIND ME or
Find me or
Find Me etc

I'm tempted to do something like
Select * from mytable t where lowercase(t.mymemo) like '%find me%'
but since this memo field could be enormous, I'm guessing that wold be 
horribly inefficient.
Is there a better way?

I think SELECT * FROM MYTABLE WHERE MYMEMO CONTAINING 'FIND ME' is case 
insensitive. One, probably better, alternative would be to use a case 
insensitive collation, but I doubt collations can be used in blobs (it should 
work in a varchar). And you're right, it will be slow since no indexes can be 
used (hopefully, we're not talking about more than a few million rows in this 
table?)...

HTH,
Set


RE: [firebird-support] Case insensitive search on a memo field

2014-09-05 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Select * from mytable t where t.mymemo like '%find me%'

You can create a computed index for this:
CREATE INDEX idxname ON mytable COMPUTED BY (lowercase(mymemo))

Such an index does not help for LIKE '%...', it can only be used if the first 
character is a real character (i.e. not % or _). Moreover, the index will not 
be used if you use a parameter rather than constant with LIKE.

Set


RE: [firebird-support] Insert ot update statements locks a table and all other instances that try to run same statement are lcoked to

2014-09-04 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
They all use READ COMMITTED isolation.

It is an application that runs in JBoss App server so I have single datasource 
defined that uses READ COMMITTED.

Blocked statements are insert and update. Selects are not blocked.

Why are inserts blocked? That should not happen unless you

a)  don’t use generators to fill values into your primary keys or

b)  have a unique constraint or similar (like triggers limiting the number 
of child records per master record)

I can understand why UPDATEs (including the UPDATE OR INSERT statement) result 
in lock conflicts and that can be unavoidable and something you have to try to 
minimize rather than eliminate. INSERTs, on the other hand, should only cause 
lock conflicts if your business logic determines it should be so.

Maybe you could show us how these lock conflicts occur (what does a typical 
insert statement that causes a lock conflict look like and are there any 
constraints/unique requirements to any of the fields?)
Set


RE: [firebird-support] Query stop working after upgrade from 2.1.5 to 2.1.6

2014-09-03 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi,

I found that after upgrade from FireBird 2.1.5 Update 1 to 2.1.6 my
query stop working with error Dynamic SQL Error SQL error code = -104
Invalid expression in the select list (not contained in either an
aggregate function or the GROUP BY clause). The same error occur on 2.5.3

select
  ke.I_ID_GRUPY,
  ke.C_SYMBOL,
  (
  select first 1 cs.C_OPIS from T_CENY_SKLADNIKI as cs
  left join T_CENY_W_OKRESIE as cwo on (cwo.I_ID_CENY_OKRS =
cs.I_ID_CENY_OKRS)
  where cs.C_SYMBOL = ke.C_SYMBOL and cwo.I_ID_CENNIKA = any (select
I_ID_CENNIKA from R_KOSZTY as kk where kk.I_ID_KOSZTY = ko.I_ID_KOSZTY)
  group by cs.C_OPIS
  ) as C_OPIS_X,
  sum(ke.N_VALUE) as N_VALUE_SUMA,
  sum(ke.N_VATIN) as N_VATIN_SUMA,
  sum(ke.N_COSTNETTO) as N_COSTNETTO_SUMA,
  sum(ke.N_COSTBRUTTO) as N_COSTBRUTTO_SUMA,
  ke.SI_WYKLADNIK, ke.SI_IDJEDNOSTKA, ke.SI_STPOTYPE,
ke.SI_CURRENCYPERVALUE
from
  R_KOSZTY k
  left join R_KOSZT_OKRESY as ko on (ko.I_ID_KOSZTY = k.I_ID_KOSZTY)
  left join R_KOSZT_ELEMENTY as ke on (ke.I_ID_KOSZT_OKRESY =
ko.I_ID_KOSZT_OKRESY)
where  ke.SI_USEINSUMMARY = 1 and  k.I_ID_KOSZTY = any (select ID from
IDY_DO_ZAPYTANIA)
group by ke.I_ID_GRUPY, ke.C_SYMBOL, C_OPIS_X, SI_WYKLADNIK,
SI_IDJEDNOSTKA, SI_STPOTYPE, SI_CURRENCYPERVALUE
order by max(ke.I_ORDER_INDEX)

Any idea how to overcome this issue?

Hi Macma!

I would have tried this query (I've assumed that ID is the primary key of 
IDY_DO_ZAPYTANIA) and checked whether the result was as desired (admittedly, 
I'm not used to using MIN in a subselect):

select
  ke.I_ID_GRUPY,
  ke.C_SYMBOL,
  (select min(cs.C_OPIS)
   from T_CENY_SKLADNIKI as cs
   join T_CENY_W_OKRESIE as cwo 
 on cwo.I_ID_CENY_OKRS = cs.I_ID_CENY_OKRS
   join R_KOSZTY kk on cwo.I_ID_CENNIKA = kk.I_ID_CENNIKA
   where cs.C_SYMBOL = ke.C_SYMBOL 
 and kk.I_ID_KOSZTY = ko.I_ID_KOSZTY) as C_OPIS_X,
  sum(ke.N_VALUE) as N_VALUE_SUMA,
  sum(ke.N_VATIN) as N_VATIN_SUMA,
  sum(ke.N_COSTNETTO) as N_COSTNETTO_SUMA,
  sum(ke.N_COSTBRUTTO) as N_COSTBRUTTO_SUMA,
  ke.SI_WYKLADNIK, ke.SI_IDJEDNOSTKA, ke.SI_STPOTYPE, ke.SI_CURRENCYPERVALUE, 
  max(ke.I_ORDER_INDEX) I_ORDER
from R_KOSZTY k
join R_KOSZT_OKRESY as ko on ko.I_ID_KOSZTY = k.I_ID_KOSZTY
join R_KOSZT_ELEMENTY as ke on ke.I_ID_KOSZT_OKRESY = ko.I_ID_KOSZT_OKRESY
join IDY_DO_ZAPYTANIA z on k.I_ID_KOSZTY = z.ID
where ke.SI_USEINSUMMARY = 1 
group by ke.I_ID_GRUPY, ke.C_SYMBOL, 3, SI_WYKLADNIK, SI_IDJEDNOSTKA, 
SI_STPOTYPE, SI_CURRENCYPERVALUE
order by 12

I don't know whether your error is a result of grouping by C_OPIS_X (I didn't 
think it was allowed), ordering by a field you do not select (I added it to the 
output, change back if this isn't the problem) or something else. Using LEFT 
JOIN as opposed to [INNER] JOIN reduces the options for the optimizer - it is 
sometimes useful as part of optimization, but only after experiencing the 
original query being slow.

If this doesn't solve your problem, please tell us more about your table 
definitions - I've no clue which fields are unique or having lots of duplicates 
in your tables, nor which indexes/keys you've defined and that limits the 
possible modifications I (and others on this list) can do to your query.

HTH,
Set

PS! I've never used Fb 2.1 myself, only 0.9.4, 1.5 and 2.5.


Re: [firebird-support] Query stop working after upgrade from 2.1.5 to 2.1.6

2014-09-03 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi,

I overcome this issue with this query

select
  ke.I_ID_GRUPY,
  ke.C_SYMBOL,
  (
  select first 1 cs.C_OPIS from T_CENY_SKLADNIKI as cs
  left join T_CENY_W_OKRESIE as cwo on (cwo.I_ID_CENY_OKRS =
cs.I_ID_CENY_OKRS)
  where cs.C_SYMBOL = ke.C_SYMBOL and cwo.I_ID_CENNIKA = any (select
I_ID_CENNIKA from R_KOSZTY as kk where kk.I_ID_KOSZTY = any (select ID
from IDY_DO_ZAPYTANIA))
  ) as C_OPIS_X,
  sum(ke.N_VALUE) as N_VALUE_SUMA,
  sum(ke.N_VATIN) as N_VATIN_SUMA,
  sum(ke.N_COSTNETTO) as N_COSTNETTO_SUMA,
  sum(ke.N_COSTBRUTTO) as N_COSTBRUTTO_SUMA,
  ke.SI_WYKLADNIK, ke.SI_IDJEDNOSTKA, ke.SI_STPOTYPE, ke.SI_CURRENCYPERVALUE
from
  R_KOSZTY k
  left join R_KOSZT_OKRESY as ko on (ko.I_ID_KOSZTY = k.I_ID_KOSZTY)
  left join R_KOSZT_ELEMENTY as ke on (ke.I_ID_KOSZT_OKRESY =
ko.I_ID_KOSZT_OKRESY)
where  ke.SI_USEINSUMMARY = 1 and  k.I_ID_KOSZTY = any (select ID from
IDY_DO_ZAPYTANIA)
group by ke.I_ID_GRUPY, ke.C_SYMBOL, C_OPIS_X, SI_WYKLADNIK,
SI_IDJEDNOSTKA, SI_STPOTYPE, SI_CURRENCYPERVALUE
order by max(ke.I_ORDER_INDEX)

I have to change where kk.I_ID_KOSZTY = ko.I_ID_KOSZTY to
kk.I_ID_KOSZTY = any (select ID from IDY_DO_ZAPYTANIA).

Good to hear you overcome your issue. I took a look at your database and query 
this evening, and to my surprise your original query executed fine on 2.5.2 
(26539)! (well, not yielding any result due to IDY_DO_ZAPYTANIA being empty, 
but removing that table gave 12 rows). An alternative query you could use (up 
to you to choose, you could try both if this is just a small test database and 
you have a bigger real database), is:

with tmp (C_SYMBOL, I_ID_KOSZTY, C_OPIS_X) as
(select cs.C_SYMBOL, kk.I_ID_KOSZTY, min(cs.C_OPIS)
 from T_CENY_SKLADNIKI as cs
 join T_CENY_W_OKRESIE as cwo 
   on cwo.I_ID_CENY_OKRS = cs.I_ID_CENY_OKRS
 join R_KOSZTY kk on cwo.I_ID_CENNIKA = kk.I_ID_CENNIKA
 group by 1, 2)
select
  ke.I_ID_GRUPY,
  ke.C_SYMBOL,
  t.C_OPIS_X,
  sum(ke.N_VALUE) as N_VALUE_SUMA,
  sum(ke.N_VATIN) as N_VATIN_SUMA,
  sum(ke.N_COSTNETTO) as N_COSTNETTO_SUMA,
  sum(ke.N_COSTBRUTTO) as N_COSTBRUTTO_SUMA,
  ke.SI_WYKLADNIK, ke.SI_IDJEDNOSTKA, ke.SI_STPOTYPE, ke.SI_CURRENCYPERVALUE 
from R_KOSZTY k
join R_KOSZT_OKRESY as ko on ko.I_ID_KOSZTY = k.I_ID_KOSZTY
join R_KOSZT_ELEMENTY as ke on ke.I_ID_KOSZT_OKRESY = ko.I_ID_KOSZT_OKRESY
join IDY_DO_ZAPYTANIA z on k.I_ID_KOSZTY = z.ID
left join tmp t 
   on ke.C_SYMBOL = t.C_SYMBOL 
  and ko.I_ID_KOSZTY = t.I_ID_KOSZTY
where ke.SI_USEINSUMMARY = 1 
group by ke.I_ID_GRUPY, ke.C_SYMBOL, t.C_OPIS_X, SI_WYKLADNIK, SI_IDJEDNOSTKA, 
SI_STPOTYPE, SI_CURRENCYPERVALUE
order by max(ke.I_ORDER_INDEX)

HTH,
Set

RE: [firebird-support] conditional select

2014-08-28 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
 Hi, I'm looking at a system that I have not touched for some years and 
 wonder if there is a way to improve this code. This all works, but is 
 there a better or more efficient way? I can't think of how to combine 
 them into one 'where' statement.
 Basically I look for a part based on increasingly tight conditions.
 /*  search conditions
   0 partno only,
   1 partno  location
   2 partno  Trans_type
   3 partno  location  Trans_type  */
 
 input parameters
  locsearch char(20),
  locsearchtype integer,
  loclocation char(1),
  loctransaction char(1)
 
 begin
for selects.partno,s.morefields.
from  stock s
where (:locsearchtype=0
  and s.partno=:locsearch)
or(:locsearchtype=1
  and s.partno=:locsearch
  and s.location=:loclocation)
or(:locsearchtype=2
  and s.partno=:locsearch
  and s.trans_type=:loctransaction)
or(:locsearchtype=3
  and s.partno=:locsearch
  and s.trans_type=:loctransaction
  and s.location=:loclocation)
into  :partno_out,:morefields_out.
do
  suspend;
 end

Hi Alan!

If you use Fb 2.5, I suppose you could try:

   for selects.partno,s.morefields.
   from  stock s
   where s.partno = :locsearch
 and s.location   is not distinct from coalesce(:loclocation,
s.location)
 and s.trans_type is not distinct from coalesce(:loctransaction, 
s.trans_type)

If :loclocation is null, then every record should match (is not distinct from 
differs from equality comparison by including cases where s.location is null). 
I don't think there's any need for locsearchtype... If you cannot use is 
distinct from or coalesce, you should at least move s.partno outside of the 
'or' bit.

HTH,
Set


RE: [firebird-support] Difficult condiion question

2014-08-28 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hello,

the following sql statement is almost done, just one thing is problematic.

In the table tlager_sum I have two types of amounts, one of typ 1, one of typ 
2. I just need the one of typ1. But if the material not in the table listet 
or just für typ 2, and there is a minimum inventory in the tteile set, then 
should I get this record too.

Expect for one constellation it works fine: It was set a minimum inventory and 
in the table tlager_sum It was present a record with an amount of typ 2 - 
then I don't get this record. How can I solve this problem in firebird? In 
Microsoft Access I can create a subquery how gets me only typ 1, whats in 
firebird the best way?

SELECT TTEILE.TEILENR, TTEILE.BEZEICHNUNG, TLAGER_SUM.MENGE, TTEILE.MINB, 
TLAGER_SUM.TYP, TTEILE.TYP
FROM TTEILE LEFT JOIN TLAGER_SUM ON TTEILE.TEILENR = TLAGER_SUM.TEILENR
WHERE (((TLAGER_SUM.MENGE)[minb]) AND ((TLAGER_SUM.TYP)=1) AND 
((TTEILE.TYP)=1)) OR (((TLAGER_SUM.MENGE) Is Null) AND ((TTEILE.MINB)0) AND 
((TTEILE.TYP)=1))
ORDER BY TTEILE.TEILENR;

Hi Olaf, I don't quite understand your question, but it is possible that you 
just need to add 'AND TLAGER_SUM.TYP = 1' to your left join. Below is the sql 
after I tried to tidy it a bit and simplify to see if that helped me understand 
your question (by the way, I don't understand [minb], is that some kind of 
parameter?).

HTH,
Set

SELECT TT.TEILENR, TT.BEZEICHNUNG, LS.MENGE, TT.MINB, LS.TYP, TT.TYP
FROM TTEILE TT
LEFT JOIN TLAGER_SUM LS 
   ON TT.TEILENR = LS.TEILENR 
  AND LS.TYP = 1
  AND LS.MENGE[minb]
  AND LS.TYP=1
WHERE TT.TYP=1 
  AND (LS.MENGE IS NOT NULL
OR TT.MINB0)
ORDER BY TT.TEILENR;


RE: [firebird-support] Difficult condiion question

2014-08-28 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
I think I have it:

SELECT TT.TEILENR, TT.BEZEICHNUNG, LS.MENGE, TT.MINB, LS.TYP, TT.TYP
FROM TTEILE TT
LEFT JOIN TLAGER_SUM LS 
ON TT.TEILENR = LS.TEILENR 
AND LS.TYP = 1

WHERE TT.TYP=1 
AND (LS.MENGE IS NOT NULL
AND LS.MENGEtt.minb
OR TT.MINB0 and ls.menge is null)
ORDER BY TT.TEILENR;

The and ls.typ = 1 should exclude all records from tlager_-sum there not typ 
1? It was fine! Thank you

Can you tell me what about the statements before the where conditions? Until 
now I don't know about.
 
Your syntax returns me too many records, some of them has entries in the table 
tlager_sum, but the amount and the present typ (1) returns me this statement, 
it is null. 

Good to hear that you figured it out, Olaf. Sorry for misleading you and 
writing code that returned records if TT.MINB  0 regardless of ls.menge. You 
can still reduce your query by one line if you want, LS.MENGE IS NOT NULL can 
simply be removed.

The statements before the WHERE condition are part of the LEFT JOIN. Typically, 
that's where you put criteria relating to the right table. If you write such 
criteria in the WHERE clause, they could (logically speaking) turn the LEFT 
JOIN into an INNER JOIN.

Set


RE: [firebird-support] Case-insensitive, unique, multi-column index

2014-08-18 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
The problem comes with the second.  (1, 'Bob Jacobs'), (2, 'Bob Jacobs'), (3, 
'BOB JACOBS'), and (4, 'bob jacobs') constitute an acceptable set of rows; 
(2, 'Bill Hafner') and (2, 'BILL HAFNER') do not.  That is, given a value for 
CORPORATION_S_KEY, there shouldn't be case-variants for the NAME value.

There are at least 3 ways of solving this, the simplest (which I recommend if 
you don't need case sensitive sorting) would be to use a case insensitive 
collation for the field (exists for many character sets).

The second option is to use a computed index: CREATE UNIQUE INDEX I_TEST_NAME 
ON TEST computed by(ID||'::'|| upper(NAME)); or just a computed index that you 
use in a unique constraint.

The third option is to have an extra field that you populate through a BEFORE 
INSERT trigger: new.UC_Equivalent = upper(NAME).

There may exist other options as well,
Svein Erling


Re: [firebird-support] Getting Invalid Request BLR at offset 49 ?

2014-08-09 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
If (:In_vin = :Out_BikeLast8Vin) then BEGIN
Update Total_sales_to_part_cost_match
 set TSPM_BIKEYEAR = :Out_BikeYear,TSPM_BIKEMAKE =
 :Out_BikeMake, TSPM_BIKEMODEL = :Out_BikeModel, TSPM_LAST8VIN =
 :Out_BikeLast8Vin;

Given that your stored procedure will update (and return) at most one
row (as far as I understand your domain) and this is something that
changes data (instead of only producing rows), I would keep it an
executable stored procedure and change the way you execute it.

Just a minor comment that's irrelevant to the original question: The update 
statement has no WHERE clause, so all records of Total_sales_to_part_cost_match 
will be updated.

Set

RE: [firebird-support] Create Date of Database Object

2014-08-04 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Hi,
 
Is it possible to see from the systems tables when a database object was 
created?
 
For instance I want to try and find out when a specific trigger was created 
on the database, is this possible?

table: MON$DATABASE
field: MON$CREATION_DATE

I think that is just the creation date (or restore date if restored) of the 
database, if there had been a creation date of the trigger, I would have 
expected that to be in the RDB$TRIGGERS table. However, I don't think there is 
such a field, and that it is more a matter of implementing a company policy to 
store the creation date of triggers in the trigger itself or it's description. 
I doubt there is a way to find out when a trigger was created if whomever wrote 
the trigger didn't do this, but I hope I'm wrong.

Set


SV: [firebird-support] Firebird caching query results

2014-08-01 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
In my environment I have a software which insert new rows on a certain table. 
This software and the firebird server is running on the same machine.

I have a software running on a client which query the the server.

The problem is there are some sort of cache, because I'm getting the old rows. 
If I query the database from the the server works fine (I get the new rows), 
but when I'm in na cliente I always get the same old rows from hours ago.

Your problem is not related to any cache, it is related to Firebird using 
versioning of records rather than locking. One version of a record may be 
visible to one transaction, whereas another version of the same record is 
visible to other transactions. This is a feature that gives you as a user more 
control.

Transactions are fundamental to Firebird, almost everything you do happen in a 
transaction. Depending on how you set it up, the transaction may either see 
records as they were when you started the transaction, or the last committed 
version. In many cases, it is important to make sure transactions are not 
running indefinitely - e.g. in our system things are rolled back one hour after 
the transaction started so that people having left a transaction open doesn't 
hinder Firebird from doing garbage collection. Systems under heavy load will 
require shorter transactions, whereas tiny systems may not notice any problems 
even with long-running transactions.

The simplest answer to your particular problem, will be to commit your 
transaction and then reopen the query. But it would be better if you read more 
about transactions in Firebird.

Another thing that may be of interest, is events. This can be used to notify 
your client that things have changed, so that the client can take appropriate 
action and reload data. Though that is a more advanced subject that can wait 
until you master transactions.

HTH,
Set

RE: [firebird-support] Skip records

2014-07-29 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
Thomas,

 I usually solve this kind of problem with recusive CTEs providing a 
 counter for the records returned, thus a simple select statement can 
 nicely filter on this kind of property without row numbers functionality.

Can you provide an example, please.

I, for one, can't imagine how a CTE could be used for such a purpose.

My imagination may be slightly more vivid than yours, Sean, I even think I 
answered something on this list with a similar recursive CTE a few years ago. 

WITH RECURSIVE TMP(Level, PK, fields) as
(SELECT 1, min(PK), whatever
 FROM table
 WHERE whatever
 UNION ALL
 SELECT t.Level + 1, t1.PK, fields
 FROM TMP t
 JOIN table t1 on t.PK  t1.PK
 LEFT JOIN table t2 on t2.PK  TMP.PK and t2.PK  t1.PK
 WHERE whatever and t2.PK is null)
SELECT *
FROM TMP
WHERE MOD(Level, 5) = 0

This has the severe drawback that it doesn't work if there's more than 1024 
records (I think, at least there's a very limited max depth of recursion), I 
consider it less intuitive than EXECUTE BLOCK, and expect it to be slower. But 
I agree that it would be interesting to see Thomas' solution.

Don't know whether windowing functions can be used in the WHERE clause, but 
when Firebird 3 is released, it would be tempting to try things like

WHERE MOD(ROW_NUMBER() OVER (ORDER BY something), 5) = 2

Set


SV: [firebird-support] How to truncate text to fit in a db field the easiest way in Firebird?

2014-07-29 Thread Svein Erling Tysvær svein.erling.tysv...@kreftregisteret.no [firebird-support]
$CATEGORY=str_replace(','',$_REQUEST['CATEGORY']);

I convert html entities to text i can use on the web pages.
I use this for being able to retrieve it back as normal characters.
I use this on all my inserts.

And, then i want to put it in the category field in the table.
Let's say the category field is 20 characters in length.

If user is writing a lot of  the text will expand, even if it is set to stop 
at 20 characters. Because it adds extra characters to the converted variable.
and if i strip the characters to fit the db field, it can be that i loose one 
' character, and then it is fucked up because it needs to of the ' for each .
How can i best do this? How can i make the text fit in the db field the 
easiest way without getting the truncated string error?

Is there another easier way?

Just keep your inserts as they are and then run

UPDATE table
SET CATEGORY = SUBSTRING(CATEGORY FROM 1 FOR 19)
WHERE PrimaryKey = :NewPK AND --or some other way to only update recently 
inserted rows
  (SUBSTRING(CATEGORY FROM 20 FOR 1) =  AND
   SUBSTRING(CATEGORY FROM 19 FOR 2)  '') OR
  (SUBSTRING(CATEGORY FROM 18 FOR 3) =  AND
   SUBSTRING(CATEGORY FROM 17 FOR 4)  '')

to delete orphan ' at the last position.

This should cover those situations where the html contains a ' or '' as the 
last characters to be stored (if the html can contain ''' or  at the end, 
you'll have to add another pair or two of lines).

I've never done this myself, but I think it should work.

HTH,
Set

  1   2   >