How do I create a report with multiple 1-M relationships? - crystal-reports

I need to create a report that shows, for each master row, two sets of child (detail) rows. In database terms you can think of this as table 'A' having a 1:M relationship to table 'B' and also a 1:M relationship to table 'C'. So, for each row from table 'A', I want to display a list of child rows from 'B' (preferably in one section) and a list of child rows from 'C' (preferably in another section). I would also prefer to avoid the use of sub-reports, if possible. How can I best accomplish this?
Thanks.

I think I understand your question correctly, ie for a given row in Table A, you want the details section(s) to show all connected rows in Table B and then all connected rows in Table C (for any number of rows in B or C, including zero). I only know of two solutions to this, neither of which is straightforward.
The first is, as you've guessed, the disliked subreport option.
The second involves some additional work in the database; specifically, creating a view that combines the entries in Table B and Table C into one table, which can then be used in the main report as a linkable object to report on and you can group on Table A as desired. How straightforward this is will depend on how similar the structures of B and C are. If they were effectively identical, the view could contain something simple like
SELECT 'B' AS DetailType, Field1, Field2, FieldLinkedToTableA
FROM TableB
UNION ALL
SELECT 'C' AS DetailType, Field1, Field2, FieldLinkedToTableA
FROM TAbleC
However, neither option will scale well to reports with lots of results (unless your server supports indexing the view).

This is exactly what Crystal was made for :)
Make a blank .rpt and connect to your data sources as you normally would.
Go to Report->Group Expert and choose your grouping field (aka Index field).
You will now see a Group Header section in your design view. This is your "Master row". The Details sections will be your "Child rows".
In the example image below, this file is grouped by {Client}. For client "ZZZZ", there are 2 records, so there are 2 details sections while all the other clients only have 1 details section.
Edit
Based on your response, how about this:
In your datasource (or perhaps using some kind of intermediary like MS Access), start SQLing as follows.
Make a subquery left joining the primary key of TblA and the foreign key of TblB. Add a third column containing a constant, e.g. "TblB"
Make a subquery left joining the primary key of TblA and the foreign key of TblC. Add a third column containing a different constant, e.g. "TblC"
Union those 2 queries together. That'll be your "index table" of your crystal report.
In Crystal, you can have multiple grouping levels. So group first by your constant column, then by the TblA primary key, then by the foreign key.
This way, all the results from TblB will be displayed first, then TblC. And with a little work, tables B & C won't even have to have the same field definitions.

You can use or create columns that are used for grouping, then group on the table A column, then the table B column, then C. (Crystal's group is not the same as t-sql "group by". In Crystal, it's more of a sorting than a grouping.)

Related

Postgres table partitioning with star schema

I have a schema with one table with the majority of data, customer, and three other tables with foreign key references to customer.entry_id which is a BIGSERIAL field. The three other tables are called location, devices and urls where we store various data related to a specific entry in the customer table.
I want to partition the customer table into monthly child tables, and have that part worked out; customer will stay as-is, each month will have a table customer_YYYY_MM that inherits from the master table with the right CHECK constraint and indexes will be created on each individual child table. Data will be moved to the correct child tables while the master table stays empty.
My question is about the other three tables, as I want to partition them as well. However, they have no date information (at all), only the reference to the primary key from the master table. How can I setup the constraints on these tables? Is it even meaningful or possible without date information?
My application logic knows where to insert all the data (it's fairly trivial), but I expect to be able to do simple SELECT queries without specifying which child tables to get it from. So this should work as you would expect from non-partitioned tables:
SELECT l.*
FROM customer c
JOIN location l USING entry_id
WHERE c.date_field > '2015-01-01'
I would partition them by the reference key. The foreign key is used in join conditions and is not usually subject to change so it fulfills the following important points:
Partition by the information that is used mostly in the WHERE clauses of the queries or other parts where partitioning can be used to filter out tables that don't need to be scanned. As one guide puts it:
The objective when defining partitions should be to allow as many queries as possible to fetch data from as few partitions as possible - ideally one.
Partition by information that is not going to be changed so that rows don't constantly need to be thrown from one subtable to another
This all depends of the size of the tables too of course. If the sizes stay small then there is no need to partition.
Read more about partitioning here.
Use views:
create view customer as
select * from customer_jan_15 union all
select * from customer_feb_15 union all
select * from customer_mar_15;
create view location as
select * from location_jan_15 union all
select * from location_feb_15 union all
select * from location_mar_15;

How do I create a drop down list?

I'm new to PostgreSQL.
I was wondering, how do I make a column a drop down list.
So i've got a table called Student. There's a column in there called "student_type", which means whether the student is a part time student, full time student or is sandwich course student.
So I want to make "student_type" a drop down list with 3 choices: "part time" student, "full time" and "sandwich".
How do I do this?
(I'm using pgAdmin to create the databse, by the way.)
A drop-down is a client side thing and should be dealt with accordingly. But as far as a relational database is involved there should exist a student_type relation with the id and type columns which you would query like this:
select st.id, st.type
from student_type st
inner join student s on s.type_id = st.id
group by st.id, st.type
order by st.type
The inner join is to make sure you don't show an option that does not exist in the student table and would therefore produce an empty result if chosen. In the client side the id should be the option value and the type the option text.
If there is no student_type relation as a consequence of bad db design or if you are only allowed to query a denormalized view, you can still use the student relation:
select distinct student_type
from student
order by student_type
In this case the student_type will be both the option value and the option text.
I think You use MS Access before. It is not possible to create such a drop-down list using pgAdmin, but it is possible to limit acceptable values in field "student_type" in a few different ways. Still, this will not be a drop-down or Combobox filed.
eg:
You can use a table with a dictionary and then use a foreign key,
You can use the constraint to check the inserted value
You can use a domain (the field is in the type of Your domain, and the domain is based on
proper constraint)
You can use trigger (before insert or update)
etc.
To put this a different way, Postgres is a database, not a user-interface
library. It doesn't have dropdown lists, text boxes, labels and all that. It is not directly usable by a human that way.
What PG can do is provide a stable source for data used by such widgets. Each widget library has its own rules for how to bind (that is, connect) to a data source. Some let you directly connect the visual component, in this case, the dropdown widget, to a database, or better, a database cursor.
With Postgres, you can create a cursor, which is an in-memory window into the result of a SELECT query of some kind, that your widget or favorite programming language binds to. In your example, the cursor or widget binding would be to the result of a "SELECT student_type FROM student_type" query.
As an aside, the values for "student_type" should not be stored only in
"student". You should have a normalized table structure, which here would give you a "student_type" table that holds the three choices, one per row. (There
are other ways to do this.) The values you specified would be the primary key column. (Alternatively, you'd have those values in a UNIQUE column with a
surrogate key as the primary key, but that's probably overkilling for a simple
lookup table.) The "student.student_type" column would then be a foreign key
into the "student_type.student_type" column.

What is the benefit of Enforce Join option in Crystal Reports?

What is the benefit the makes SAP Crystal reports Enforce Join default option in Link Dialog is "Not Enforced"?
Is it performance issue? because I noticed if you don't select field from the joined table it'll generate SELECT query with only fields of the selected Table only without any joins.
here's some information about the Enforce Join options:
Not Enforced: When you select this option, the link
you've created is used only if it's
explicitly required by the Select
statement. This is the default
option. Your users can create reports
based on the selected tables without
restriction (that is, without
enforcement based on other tables).
Enforced From: When you select this
option, if the "to" table for the
link is used, the link is enforced.
For example, if you create a link
from Table A to Table B using Enforce
From and select only a field from
Table B, the Select statement will
still include the join to Table A
because it is enforced. Conversely,
selecting only from Table A with the
same join condition will not cause
the join to Table B to be enforced.
Enforced To: When you select this
option, if the "from" table for the
link is used, the link is enforced.
For example, if you create a link
from Table A to Table B using Enforce
To and select only a field from Table
A, the join to Table B will be
enforced, and the Select statement
that is generated will include both
tables.
Enforced Both: When you select this
option, if either the "from" table or
the "to" table for this link is used,
the link is enforced.
The "enforced" part is used to FORCE the inclusion of tables that contain fields that are NOT used in the report/select conditions.
Well crap, that's what you said.
My understanding:
If you have two tables (tbl_A, tbl_B) w/ a link-able field, and you don't USE any field from the second table, it can be dropped from the select, and the "regular" effects of the join may disappear.
Select
'You're account is in default!' as Message,
tbl_A.full_name, tbl_A.street_address, tbl_A.city, tbl_A.blah_blah
From
all_customers tbl_A,
delinquent_accounts tbl_B
Where
tbl_A.account_no = tbl_B.account_no
Without the enforced join, might wind up as
Select
'You're account is in default!' as Message,
tbl_A.full_name, tbl_A.street_address, tbl_A.city, tbl_A.blah_blah
From
all_customers tbl_A,
In other words, you might wind up setting dunning letters to your whole customer base instead of just the delinquent accounts. (Which is why we test reports before implementing them, I guess).

Django-ORM Left join with all columns of both tables

i have two tables A and B, i need all the columns of both tables using django ORM(left join).
i am new bee to django and programming please help.
One way is to use the .values() callable on your query (though what you are asking is not very clear). This returns a querydict, rather than a queryset, but behaves more like a left join done SQL directly into the database - i.e returns the rows with null entries from table B.
Assuming table A has a foreign key to table B in the models file.
TableA.object.filter(your filters here).values(tableA__field1, tableA__field2 , ... \
tableB__field1, tableB__field2, etc).
https://docs.djangoproject.com/en/1.3/topics/db/aggregation/#values

PostgreSQL: dynamic row values (?)

Oh helloes!
I have two tables, first one (let's call it NameTable) is preset with a set of values (id, name) and the second one (ListTable) is empty but with same columns.
The question is: How can I insert into ListTable a value that comes from NameTable? So that if I change one name in the NameTable then automagically the values in ListTable are updated aswell.
Is there INSERT for this or does the tables has to be created in some special manner?
Tried browsing the manual but without success :(
The suggestion for using INSERT...SELECT is the best method for moving between tables in the same database.
However, there's another way to deal with the auto-update requirement.
It sounds like these are your criteria:
Table A is defined with columns (x,y)
(x,y) is unique
Table B is also defined with columns (x,y)
Table A is a superset of Table B
Table B is to be loaded with data from Table A and needs to remain in sync with UPDATEs on Table A.
This is a job for a FOREIGN KEY with the option ON UPDATE CASCADE:
ALTER TABLE B ADD FOREIGN KEY (x,y) REFERENCES A (x,y) ON UPDATE CASCADE;
Now, not only will it auto-update Table B when Table A is updated, table B is protected against containing (x,y) pairs that do not exist in Table A. If you want records to auto-delete from Table B when deleted from Table A, add "ON UPDATE DELETE."
Hmmm... I'm a bit confused about exactly what you want to do or why, but here are a couple of pointers towards things you might want to take a look at: table inheritance, triggers and rules.
Table inheritance in postgresql allows a table to share the data of a another table. So, if you add a row to the base table, it won't show up in the inherited table, but if you add a row to the inherited table, it will now show up in both tables and updates in either place will reflect it in both tables.
Triggers allow you to setup code that will be run when insert, update or delete operations happen on a table. This would allow you to add the behavior you describe manually.
Rules allow you to setup a rule that will replace a matching query with an alternative query when a specific condition is met.
If you describe your problem further as in why you want this behavior, it might be easier to suggest the right way to go about things :-)