 |
|
 |
|
Next: The Price of Internet Store is 1000 Rubles only.
|
| Author |
Message |
External

Since: Jan 15, 2008 Posts: 83
|
(Msg. 1) Posted: Fri Aug 22, 2008 12:26 pm
Post subject: separate columns or separate table? Archived from groups: comp>databases (more info?)
|
|
|
Consider a flat file formatted according to the following Cobol copybook:
05 TRFL-DATE PIC 9(9) COMP-3.
05 TRFL-TIME PIC 9(5) COMP-3.
05 TRFL-CALLING-CUST PIC 9(9) COMP-3.
05 TRFL-BILLING-BR PIC 9(3) COMP-3.
05 TRFL-BILLING-ACCT-BR PIC 9(3) COMP-3.
05 TRFL-BILLING-ACCT-NBR PIC 9(9) COMP-3.
05 TRFL-BILLING-ACCT-TYPE PIC X.
05 TRFL-WAIVE-ACCT-CHG-IND PIC X.
05 TRFL-MULTI-ACCT-CALL-IND PIC X.
05 TRFL-MULTI-ACCT-ORIG-DATE PIC 9(9) COMP-3.
05 TRFL-MULTI-ACCT-ORIG-TIME PIC 9(5) COMP-3.
05 TRFL-COMMENTS PIC X(54).
05 TRFL-SERVICES-INFO.
10 TRFL-SVC-OCC OCCURS 32 TIMES.
15 TRFL-SVC-SEL PIC X.
05 TRFL-OPERATOR PIC X(3).
TRLF-SERVICES-INFO is a "table" (or array, if you prefer) that has 32 one
character occurances.
This is a "customer call tracking" file. For each call made, the CSR can
chose between 1 and 32 reasons why the customer called; which bank services
they called about or utilized (like, they wanted their account balance;
wanted to order new checks; wanted to make a transfer between accounts;
etc.).
I would like to replace the use of this file with the use of an RDBMS (DB2,
specifically). Most of it is straight-forward. It's the "services table"
that is getting me. My first thought is that there would be a SERVICES
table that is a "child" of the CALLS table. Each call will have zero or
more services related to it. So this is what I have:
CREATE TABLE CALLTRAK.SERVICE_CODES (
CODE CHAR(1) NOT NULL
, DESCRIPTION VARCHAR(50) NOT NULL
, CONSTRAINT SERVICE_CODES_PK PRIMARY KEY (CODE)
)
CREATE TABLE CALLTRAK.CALLS (
CALL_ID INTEGER NOT NULL
GENERATED ALWAYS AS IDENTITY
, DATE DATE NOT NULL
WITH DEFAULT
, TIME TIME NOT NULL
WITH DEFAULT
, CUST_NBR DECIMAL(9) NOT NULL
, BILL_BRCH DECIMAL(3) NOT NULL
, BRCH_NBR DECIMAL(3) NOT NULL
, ACCT_NBR DECIMAL(10) NOT NULL
, ACCT_TYPE CHAR(1) NOT NULL
, WAIVE_CHG_YN CHAR(1) NOT NULL
, MULTI_ACCT_CALL_IND CHAR(1) NOT NULL
, MULTI_ACCT_ORIG_DATETIME TIMESTAMP
, COMMENTS VARCHAR(54) NOT NULL
, BILL_ACCT_TYP CHAR(1) NOT NULL
, OPERATOR CHAR(3) NOT NULL
, CONSTRAINT CALLS_PK PRIMARY KEY (CALL_ID)
, CONSTRAINT ACCT_TYPE CHECK(ACCT_TYPE IN ('D','S','L',' '))
, CONSTRAINT WAIVE_CHG_YN CHECK(WAIVE_CHG_YN IN ('Y','N'))
, CONSTRAINT MULTI_ACCT_CALL_IND CHECK(MULTI_ACCT_CALL_IND
IN ('N','B','C','E'))
)
CREATE TABLE CALLTRAK.SERVICES (
SERVICES_ID INTEGER NOT NULL
GENERATED ALWAYS AS IDENTITY
, CALL_ID INTEGER NOT NULL
, SERVICE_CODE CHAR(1) NOT NULL
, CONSTRAINT SERVICES_PK PRIMARY KEY (SERVICES_ID)
, CONSTRAINT CALL_ID_FK FOREIGN KEY (CALL_ID)
REFERENCES CALLTRAK.CALLS (CALL_ID)
ON DELETE CASCADE
, CONSTRAINT SERVICE_CODE_FK FOREIGN KEY (SERVICE_CODE)
REFERENCES CALLTRAK.SERVICE_CODES
(CODE)
, CONSTRAINT SERVICES_UK1 UNIQUE (CALL_ID, SERVICE_CODE)
)
This all seems pretty reasonable, with one exception. As far as I can tell,
for each call I have to do a single insert into the CALLS table followed by
1 to 32 inserts in to the SERVICES table. This, umm, kind of bugs me. I'm
wanting to do a single insert. Maybe that's not rational, but its my
inclination.
If I were to add to the CALLS table 32 columns, named after the service type
(BALANCE_INQ_YN, TELEPHONE_TRANSFER_YN, CHECK_ORDER_YN, etc.) then I could
do a single insert. But this doesn't feel quite right. I also have a
thought of adding a field to the SERVICE_CODES table that indicates whether
or not a service "counts against" a customer or not. By that I mean that if
a customer makes more than a certain number of calls for certain reasons we
will bill that customer for those calls. (Yes, we are a bank; but we're
still pretty reasonable!) If I used the "named columns" method then I don't
think I'd even be able to utilize the SERVICE_CODES table. With the
SERVICES in a separate table I imagine I'd be able to say something like:
SELECT ...
FROM CALLTRAK.CALLS
WHERE CALL_ID IN (
SELECT CALL_ID FROM CALLTRAK.SERVICES
WHERE SERVICE_CODE IN (
SELECT CODE FROM CALLTRAK.SERVICE_CODES
WHERE BILLABLE = 'Y'));
This would give me all of the calls that had billable services.
Anyway, I am on the right track? Should I just "get over" my dislike of the
multiple inserts thing? Is there a third, better, direction I should be
going?
Thanks,
Frank >> Stay informed about: separate columns or separate table? |
|
| Back to top |
|
 |  |
External

Since: Apr 02, 2008 Posts: 68
|
(Msg. 2) Posted: Tue Aug 26, 2008 5:52 am
Post subject: Re: separate columns or separate table? [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
Frank,
> If I were to add to the CALLS table 32 columns, named after the service type(BALANCE_INQ_YN, TELEPHONE_TRANSFER_YN, CHECK_ORDER_YN, etc.) then I could do a single insert. But this doesn't feel quite right. <
I am having the same feeling and would go the second way you
suggested, i. e. create a "Used_Services" Table. The insert might be
easier with your 32 boolean columns, but any reporting and SELECT
statement will become very difficult or be impossible (as you
correctly stated already).
brgds
Philipp Post >> Stay informed about: separate columns or separate table? |
|
| Back to top |
|
 |  |
External

Since: Jan 02, 2008 Posts: 152
|
(Msg. 3) Posted: Wed Aug 27, 2008 9:01 am
Post subject: Re: separate columns or separate table? [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
On Aug 22, 1:26 pm, "Frank Swarbrick"
wrote:
> Consider a flat file formatted according to the following Cobol copybook:
>
> 05 TRFL-DATE PIC 9(9) COMP-3.
> 05 TRFL-TIME PIC 9(5) COMP-3.
> 05 TRFL-CALLING-CUST PIC 9(9) COMP-3.
> 05 TRFL-BILLING-BR PIC 9(3) COMP-3.
> 05 TRFL-BILLING-ACCT-BR PIC 9(3) COMP-3.
> 05 TRFL-BILLING-ACCT-NBR PIC 9(9) COMP-3.
> 05 TRFL-BILLING-ACCT-TYPE PIC X.
> 05 TRFL-WAIVE-ACCT-CHG-IND PIC X.
> 05 TRFL-MULTI-ACCT-CALL-IND PIC X.
> 05 TRFL-MULTI-ACCT-ORIG-DATE PIC 9(9) COMP-3.
> 05 TRFL-MULTI-ACCT-ORIG-TIME PIC 9(5) COMP-3.
> 05 TRFL-COMMENTS PIC X(54).
> 05 TRFL-SERVICES-INFO.
> 10 TRFL-SVC-OCC OCCURS 32 TIMES.
> 15 TRFL-SVC-SEL PIC X.
> 05 TRFL-OPERATOR PIC X(3).
>
> TRLF-SERVICES-INFO is a "table" (or array, if you prefer) that has 32 one
> character occurances.
>
> This is a "customer call tracking" file. For each call made, the CSR can
> chose between 1 and 32 reasons why the customer called; which bank services
> they called about or utilized (like, they wanted their account balance;
> wanted to order new checks; wanted to make a transfer between accounts;
> etc.).
so each service is performed AT MOST once per call? looks like it
based on the COBOL
>
> I would like to replace the use of this file with the use of an RDBMS (DB2,
> specifically). Most of it is straight-forward. It's the "services table"
> that is getting me. My first thought is that there would be a SERVICES
> table that is a "child" of the CALLS table. Each call will have zero or
> more services related to it. So this is what I have:
>
> CREATE TABLE CALLTRAK.SERVICE_CODES (
> CODE CHAR(1) NOT NULL
> , DESCRIPTION VARCHAR(50) NOT NULL
> , CONSTRAINT SERVICE_CODES_PK PRIMARY KEY (CODE)
> )
>
> CREATE TABLE CALLTRAK.CALLS (
> CALL_ID INTEGER NOT NULL
> GENERATED ALWAYS AS IDENTITY
> , DATE DATE NOT NULL
> WITH DEFAULT
> , TIME TIME NOT NULL
> WITH DEFAULT
> , CUST_NBR DECIMAL(9) NOT NULL
> , BILL_BRCH DECIMAL(3) NOT NULL
> , BRCH_NBR DECIMAL(3) NOT NULL
> , ACCT_NBR DECIMAL(10) NOT NULL
> , ACCT_TYPE CHAR(1) NOT NULL
> , WAIVE_CHG_YN CHAR(1) NOT NULL
> , MULTI_ACCT_CALL_IND CHAR(1) NOT NULL
> , MULTI_ACCT_ORIG_DATETIME TIMESTAMP
> , COMMENTS VARCHAR(54) NOT NULL
>
> , BILL_ACCT_TYP CHAR(1) NOT NULL
>
> , OPERATOR CHAR(3) NOT NULL
>
> , CONSTRAINT CALLS_PK PRIMARY KEY (CALL_ID)
>
> , CONSTRAINT ACCT_TYPE CHECK(ACCT_TYPE IN ('D','S','L',' '))
>
> , CONSTRAINT WAIVE_CHG_YN CHECK(WAIVE_CHG_YN IN ('Y','N'))
>
> , CONSTRAINT MULTI_ACCT_CALL_IND CHECK(MULTI_ACCT_CALL_IND
>
> IN ('N','B','C','E'))
>
> )
>
> CREATE TABLE CALLTRAK.SERVICES (
>
> SERVICES_ID INTEGER NOT NULL
>
> GENERATED ALWAYS AS IDENTITY
why the ID?? you don't need it!
>
> , CALL_ID INTEGER NOT NULL
>
> , SERVICE_CODE CHAR(1) NOT NULL
>
> , CONSTRAINT SERVICES_PK PRIMARY KEY (SERVICES_ID)
>
> , CONSTRAINT CALL_ID_FK FOREIGN KEY (CALL_ID)
>
> REFERENCES CALLTRAK.CALLS (CALL_ID)
>
> ON DELETE CASCADE
>
> , CONSTRAINT SERVICE_CODE_FK FOREIGN KEY (SERVICE_CODE)
>
> REFERENCES CALLTRAK.SERVICE_CODES
> (CODE)
> , CONSTRAINT SERVICES_UK1 UNIQUE (CALL_ID, SERVICE_CODE)
> )
The PK of this table should be (CALL_ID, SERVICE_CODE) Why add the
indirect ID column
>
> This all seems pretty reasonable, with one exception. As far as I can tell,
> for each call I have to do a single insert into the CALLS table followed by
> 1 to 32 inserts in to the SERVICES table. This, umm, kind of bugs me. I'm
> wanting to do a single insert. Maybe that's not rational, but its my
> inclination.
Can you create a view with an INSTEAD OF trigger? (You failed to
mention WHICH DBMS you use. I only know it isn't Oracle.)
In your application level code, the services are just in an array,
right? So codewise it is just one INSERT inside a loop.
Your inclination is right, just the code structure needs to match your
inclination. As services are picked, shove them into a list (or array
or other loopable structure).
>
> [snip] If I used the "named columns" method then I don't
> think I'd even be able to utilize the SERVICE_CODES table. With the
> SERVICES in a separate table I imagine I'd be able to say something like:
>
> SELECT ...
> FROM CALLTRAK.CALLS
> WHERE CALL_ID IN (
> SELECT CALL_ID FROM CALLTRAK.SERVICES
> WHERE SERVICE_CODE IN (
> SELECT CODE FROM CALLTRAK.SERVICE_CODES
> WHERE BILLABLE = 'Y'));
>
> This would give me all of the calls that had billable services.
Yes.
>
> Anyway, I am on the right track? Should I just "get over" my dislike of the
> multiple inserts thing? Is there a third, better, direction I should be
> going?
>
> Thanks,
> Frank
It really shouldn't be multiple inserts, so...
....just get over it. 8^)
Ed >> Stay informed about: separate columns or separate table? |
|
| Back to top |
|
 |  |
External

Since: Aug 28, 2008 Posts: 1
|
(Msg. 4) Posted: Thu Aug 28, 2008 1:44 am
Post subject: Re: separate columns or separate table? [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
Hello.
I should say sorry, if I get it wrong, but what about bit fields then?
You could store IDs in SERVICE_CODES table as a powers of 2 and then
store and retrieve them from SERVICES table using BITAND operation?
Not sure how this compares with relational databases theory, but it
just struck me as an idea...
--
Hope this helps,
JB >> Stay informed about: separate columns or separate table? |
|
| Back to top |
|
 |  |
External

Since: Jan 15, 2008 Posts: 83
|
(Msg. 5) Posted: Thu Aug 28, 2008 5:37 pm
Post subject: Re: separate columns or separate table? [Login to view extended thread Info.] Archived from groups: per prev. post (more info?)
|
|
|
>>> On 8/27/2008 at 10:01 AM, in message
, Ed
Prochak wrote:
> On Aug 22, 1:26 pm, "Frank Swarbrick"
> wrote:
>> Consider a flat file formatted according to the following Cobol
> copybook:
>>
>> 05 TRFL-DATE PIC 9(9) COMP-3.
>> 05 TRFL-TIME PIC 9(5) COMP-3.
>> 05 TRFL-CALLING-CUST PIC 9(9) COMP-3.
>> 05 TRFL-BILLING-BR PIC 9(3) COMP-3.
>> 05 TRFL-BILLING-ACCT-BR PIC 9(3) COMP-3.
>> 05 TRFL-BILLING-ACCT-NBR PIC 9(9) COMP-3.
>> 05 TRFL-BILLING-ACCT-TYPE PIC X.
>> 05 TRFL-WAIVE-ACCT-CHG-IND PIC X.
>> 05 TRFL-MULTI-ACCT-CALL-IND PIC X.
>> 05 TRFL-MULTI-ACCT-ORIG-DATE PIC 9(9) COMP-3.
>> 05 TRFL-MULTI-ACCT-ORIG-TIME PIC 9(5) COMP-3.
>> 05 TRFL-COMMENTS PIC X(54).
>> 05 TRFL-SERVICES-INFO.
>> 10 TRFL-SVC-OCC OCCURS 32 TIMES.
>> 15 TRFL-SVC-SEL PIC X.
>> 05 TRFL-OPERATOR PIC X(3).
>>
>> TRLF-SERVICES-INFO is a "table" (or array, if you prefer) that has 32
one
>> character occurances.
>>
>> This is a "customer call tracking" file. For each call made, the CSR
> can
>> chose between 1 and 32 reasons why the customer called; which bank
> services
>> they called about or utilized (like, they wanted their account balance;
>> wanted to order new checks; wanted to make a transfer between accounts;
>> etc.).
>
> so each service is performed AT MOST once per call? looks like it
> based on the COBOL
I wouldn't say that each services is *performed* at most once per call.
Only that each services is *recorded* at most once per call.
Actually, that isn't quite correct. The table is actually what we call
"call segments", where a "call" can consist of more than one call segment,
where different segments within the same call can pertain to the same
customer but different customer accounts. Or something like that!
Probably I should rename this table. I didn't understand the 'call segment'
idea at the time I created the table.
>> I would like to replace the use of this file with the use of an RDBMS
> (DB2,
>> specifically). Most of it is straight-forward. It's the "services
> table"
>> that is getting me. My first thought is that there would be a SERVICES
>> table that is a "child" of the CALLS table. Each call will have zero or
>> more services related to it. So this is what I have:
>>
>> CREATE TABLE CALLTRAK.SERVICE_CODES (
>> CODE CHAR(1) NOT NULL
>> , DESCRIPTION VARCHAR(50) NOT NULL
>> , CONSTRAINT SERVICE_CODES_PK PRIMARY KEY (CODE)
>> )
>>
>> CREATE TABLE CALLTRAK.CALLS (
>> CALL_ID INTEGER NOT NULL
>> GENERATED ALWAYS AS IDENTITY
>> , DATE DATE NOT NULL
>> WITH DEFAULT
>> , TIME TIME NOT NULL
>> WITH DEFAULT
>> , CUST_NBR DECIMAL(9) NOT NULL
>> , BILL_BRCH DECIMAL(3) NOT NULL
>> , BRCH_NBR DECIMAL(3) NOT NULL
>> , ACCT_NBR DECIMAL(10) NOT NULL
>> , ACCT_TYPE CHAR(1) NOT NULL
>> , WAIVE_CHG_YN CHAR(1) NOT NULL
>> , MULTI_ACCT_CALL_IND CHAR(1) NOT NULL
>> , MULTI_ACCT_ORIG_DATETIME TIMESTAMP
>> , COMMENTS VARCHAR(54) NOT NULL
>
>>
>> , BILL_ACCT_TYP CHAR(1) NOT NULL
>
>>
>> , OPERATOR CHAR(3) NOT NULL
>
>>
>> , CONSTRAINT CALLS_PK PRIMARY KEY (CALL_ID)
>
>>
>> , CONSTRAINT ACCT_TYPE CHECK(ACCT_TYPE IN ('D','S','L','
> '))
>>
>> , CONSTRAINT WAIVE_CHG_YN CHECK(WAIVE_CHG_YN IN ('Y','N'))
>
>>
>> , CONSTRAINT MULTI_ACCT_CALL_IND CHECK(MULTI_ACCT_CALL_IND
>
>>
>> IN ('N','B','C','E'))
>
>>
>> )
>
>>
>> CREATE TABLE CALLTRAK.SERVICES (
>
>>
>> SERVICES_ID INTEGER NOT NULL
>
>>
>> GENERATED ALWAYS AS IDENTITY
>
> why the ID?? you don't need it!
Bad habit?
>>
>> , CALL_ID INTEGER NOT NULL
>
>>
>> , SERVICE_CODE CHAR(1) NOT NULL
>
>>
>> , CONSTRAINT SERVICES_PK PRIMARY KEY (SERVICES_ID)
>
>>
>> , CONSTRAINT CALL_ID_FK FOREIGN KEY (CALL_ID)
>
>>
>> REFERENCES CALLTRAK.CALLS (CALL_ID)
>
>>
>> ON DELETE CASCADE
>
>>
>> , CONSTRAINT SERVICE_CODE_FK FOREIGN KEY (SERVICE_CODE)
>
>>
>> REFERENCES CALLTRAK.SERVICE_CODES
>> (CODE)
>> , CONSTRAINT SERVICES_UK1 UNIQUE (CALL_ID, SERVICE_CODE)
>> )
>
> The PK of this table should be (CALL_ID, SERVICE_CODE) Why add the
> indirect ID column
Does this table really need a PK at all? Once a "call segment" has been
added it can no longer be altered in any way (except perhaps being deleted
when it's really old).
Actually, I guess it make sense to have a PK if only to enforce uniqueness
(instead of the SERVICES_UK1 constraint).
>> This all seems pretty reasonable, with one exception. As far as I can
> tell,
>> for each call I have to do a single insert into the CALLS table followed
> by
>> 1 to 32 inserts in to the SERVICES table. This, umm, kind of bugs me.
> I'm
>> wanting to do a single insert. Maybe that's not rational, but its my
>> inclination.
>
> Can you create a view with an INSTEAD OF trigger? (You failed to
> mention WHICH DBMS you use. I only know it isn't Oracle.)
DB2/LUW 9.5. INSTEAD OF triggers are available, but I am not understanding
how one would be utilized here.
> In your application level code, the services are just in an array,
> right? So codewise it is just one INSERT inside a loop.
Yes. I didn't mean to imply I'd have 32 individual INSERT statements. Just
that the single INSERT would be executed from 1 to 32 times.
> Your inclination is right, just the code structure needs to match your
> inclination. As services are picked, shove them into a list (or array
> or other loopable structure).
>
>>
>> [snip] If I used the "named columns" method then I don't
>> think I'd even be able to utilize the SERVICE_CODES table. With the
>> SERVICES in a separate table I imagine I'd be able to say something
> like:
>>
>> SELECT ...
>> FROM CALLTRAK.CALLS
>> WHERE CALL_ID IN (
>> SELECT CALL_ID FROM CALLTRAK.SERVICES
>> WHERE SERVICE_CODE IN (
>> SELECT CODE FROM CALLTRAK.SERVICE_CODES
>> WHERE BILLABLE = 'Y'));
>>
>> This would give me all of the calls that had billable services.
>
> Yes.
>
>>
>> Anyway, I am on the right track? Should I just "get over" my dislike of
> the
>> multiple inserts thing? Is there a third, better, direction I should be
>> going?
>>
>> Thanks,
>> Frank
>
> It really shouldn't be multiple inserts, so...
>
> ...just get over it. 8^)
To me it is still multiple inserts, unless I am misunderstanding what you
are saying.
In DB2 for z/OS it looks like I could do something like this:
01 HOST-ARRAYS.
05 TCS-ID-ARRAY PIC S9(  COMP OCCURS 32.
05 TCS-SERVICE-CODE-ARRAY PIC X OCCURS 32.
77 NBR-OF-SERVICES PIC S9(4) COMP.
EXEC SQL
INSERT INTO CALLTRAK.SERVICES (
CALL_ID
, SERVICE_CODE
)
VALUES (
:TCS-ID-ARRAY
, :TCS-SERVICE-CODE-ARRAY
)
FOR :NBR-OF-SERVICES TIMES
ATOMIC
END-EXEC
This would be ideal, but unfortunately it is not available on the LUW
platform.
Thanks for your thoughts.
Frank >> Stay informed about: separate columns or separate table? |
|
| Back to top |
|
 |  |
| Related Topics: | Self join and duplicate columns - Sorry if this has been asked before. I have a table on which I'd like to do a self join. The table contains people, and I'd like spouses on the same row. Husband and wife will have the same 'uniqueID' value. Trouble is, I'm getting each couple back..
Hundreds of columns, index on all of those. - Topic: Hundreds of columns, index would be required on all of the columns. Hi! How could this be implemented? There are several items (or rows). One item (or row) has e.g. even 900 columns. An index would be needed on every column. Would it be..
concat() field in a table? - Can I add a field that is a concat of two or more fields already in a table such that inserting values A and B populates the concat field with the value AB? I'm doing some concatting in a query and thought it might speed things up if such a value already...
Table design question - I am looking at a new database design for the association I belong to. In particular I am looking at how to handle telephones, addresses, and email. All of these could have zero to as many as five values for any of the entities. Our society has the....
How to insert a 100000 records in access table with in les.. - Hey Guy I am working with Microsoft Visual Basic 6.0 and (Ms access/Sql Server 2000).Now, I have to insert a large numbers of record(Approximately 100000 Rows) in a access table in less time(within 1 minutes) by using visual basic 6.0. This task.... |
|
You can post new topics in this forum You can reply to topics in this forum You can edit your posts in this forum You can delete your posts in this forum You can vote in polls in this forum
|
|
|
|
 |
|
|