Dynamic Condition Objects - business-objects

In BO XI 3.1, is it possible to create a condition object that filters on multiple tables, without adding all of those tables to the query if they weren't already present?
For example, if I have several tables which all contain both current and historical data, and each table has a flag to indicate if the record is current or historical - can I create a single "Current Data" condition that filters all of such tables to pull only current data? The catch would be that the query might not be selecting from all of these tables, and I don't want the inclusion of the condition to add joins to tables I'm not selecting from.
In other words, can a condition check which tables are being used by the query and apply filters only on those tables?

You could add a self-restricting join to each of those tables, and use an #prompt function to ask whether to return current data or historical data. If you use the same text and same datatype for all of the prompts in each self-restricting join, the prompt will only be shown once, and will only be applied to the tables that are actually used in the generated query.
The self-restricting join could look something like:
<table>.<history_flag>
= #Prompt('Select current or historical data','A',{'C','H'}, Mono, constrained, , {'C'})
In the above example, we assume that the flag is an alphanumeric column (A) with values C or H ({'C','H'}). The user is only allowed to pick from these two values (constrained) and only one value can be chosen (Mono). The default choice is set to current data ({'C'}).
Have a look at the Universe Designer guide for the #prompt syntax. Self-restricting joins are explained in the same manual.

Related

making unique records in MS access

I have 1.7 million records in an access table sorted A to Z. the records are not unique and there are repeated records. I want to make them unique based on their frequency. if a record has been repeated 4 times I want the first one to get "-1" at the end of the record value, the second record get "-2" and so on. in this way similar records will become unique. all similar record are beside each other because of sorting. in excel I do this task by an If function (if this cell value<>the cell value above then "1" else above repeat number plus 1) but in access I don't know what to do (I'm a beginner).
finally I want to add a column to original table which is (original record value - repeat number).
I appreciate your help
Note about sort order:
Sort order in a relational database is not concrete like in a spreadsheet. There is no concept of rows being "next to each other", unless in context of an index. An index is largely a tool for the database to handle the data more efficiently (and to aid in defining uniqueness). The order itself is still largely dynamic because the order of a particular query can be specified differently from the index (or from storage order) and this does not change how the data is actually stored. Being "next to each other" is essentially a useless concept in SQL queries, unless you mean "next to each other numerically", for instance with an AutoNumber field or with the "repeat numbers" you want to add. Unlike in a spreadsheet, you cannot refer to the row "just above this row" or the "row offset by 2 from the 'current' row".
Solution
Regardless of whether or not you will use the AutoNumber column later, add a Long Integer AutoNumber column anyway. This column is named [ID] in the example code. Why? Because until you add something to allow the database to differentiate between the rows, there is technically no way using standard SQL to reliably reference individual duplicates since there is no way to distinguish individual rows. Even though you say that there are other differentiating columns, your own description rules out using them as a reliable key in referring to specific rows. (Even without such a differentiating column, Access can technically distinguish between rows. Iterating through a DAO.Recordset object in VBA would work, but perhaps not very elegant / efficient.)
Also add a new integer column for counting repeats, which below is named [DupeIndex]. A separate field is preferred (necessary?) because it allows continued reference to the original, unaltered duplicate values. If the reference number were directly updated, it would no longer match other fields and so would not be easily detected as a duplicate anymore. The following solution relies on grouping of ALL duplicate values, even those already "marked" with a [DupeIndex] number.
You should also realize that in comparing different data sets, that having separate fields allows more flexibility in matching the data. Having the values appended to the reference number complicates comparison, since you likely not only want to compare rows with the same duplication index, rather you will want to compare all possible combinations. For example, comparing records 123-1 in one set to 123-4 in another... how do you select such rows in an automated fashion? You don't want to have to manually code all combinations, but that's what you'll end up doing if you don't keep them separate like {123,1} and {123,4}.
Create and save this as a named query [Duplicates]. This query is referenced by later queries. It could instead be embedded as a sub query, but my preferences is to use saved queries for easier visualization and debugging in Access:
SELECT Data.RefNo, Count(Data.ID) AS Dupes, Max(Data.DupeIndex) AS IndexMax
FROM Data
GROUP BY Data.RefNo
HAVING Count(Data.ID) > 1
Execute the following to create a temporary table with new duplicate index values:
SELECT D1.ID, D1.RefNo,
IIf([Duplicates].[IndexMax] Is Null,0,[Duplicates].[IndexMax])
+ 1
+ (SELECT Count(D2.ID) FROM Data As D2
WHERE D2.[RefNo]=[D1].[RefNo]
And [D2].[DupeIndex] Is Null
And [D2].[ID]<[D1].[ID]) AS NewIndex
INTO TempIndices
FROM Data AS D1 INNER JOIN Duplicates ON D1.RefNo = Duplicates.RefNo
WHERE (D1.DupeIndex Is Null);
Execute the update query to set the new duplicate index values:
UPDATE Data
INNER JOIN TempIndices ON Data.ID = TempIndices.ID
SET Data.DupeIndex = [NewIndex]
Optionally remove the AutoNumber field and now assign the combined [RefNo] and new [DupeIndex] as primary key. The temporary table can also be deleted.
Comments about the queries:
Solution assume that [DupeIndex] is Null for unprocessed duplicates.
Solution correctly handles existing duplicate index numbers, only updating duplicate rows without an unique index.
Access has rather strict conditions for UPDATE queries, namely that updates are not based on circular references and/or that that joins will not produce multiple updates for the same row, etc. The temporary table is necessary in this case, since the query determining new index values refers multiple times in sub queries to the very column that is being updated. (If the update is attempted using joins on the subqueries, for example, Access complains that Operation must use an updatable query.)

How do the fields in "SHOW COLUMNS" command map to specific tables?

Here is a View called viewwithcommonfield :
SELECT
`schematopologytest01`.`talpha`.`CommonField` AS `CommonField_tAlpha`,
`schematopologytest01`.`tbeta`.`CommonField` AS `CommonField_tBeta`
FROM
(`schematopologytest01`.`talpha`
JOIN `schematopologytest01`.`tbeta`)
When I execute
SHOW FULL fields FROM viewwithcommonfield IN SchemaTopologyTest01
I get this:
How do I map the fields back to specific tables? Can I write a view against the tables in information_schema?
Here are the table structures that are referenced in the view. The tables share a common field called CommonField:
No, there is no metadata available to map views of a column back to the original column in a base table. That would require multiple tables, because any given expression in the select-list may reference multiple columns from different tables.
Consider:
SELECT CONCAT(
`schematopologytest01`.`talpha`.`AlphaFieldA`,
`schematopologytest01`.`tbeta`.`BetaFieldE`) AS `ConcatenatedField`
FROM `schematopologytest01`.`talpha`
JOIN `schematopologytest01`.`tbeta` ON ...
Which table and column would ConcatenatedField list as its origin? It would have to be stored in two rows of another INFORMATION_SCHEMA table.
There are also select-list expressions possible in a view that don't reference any base table:
CREATE VIEW ViewNow AS SELECT NOW() AS `now`;
What about columns that are themselves scalar subqueries? Or references to stored functions? Or an aggregate function like COUNT() or SUM() where the value is not found in any base table?
Many views do not derive their data from base tables deterministically at all. Edit: What I mean is that it's not always possible to know which rows or columns are the source of data in a view, because they results are combined in some ways. It's probably more clear to say that reversing the query to get the original data is not always possible, depending on the query.
It's not possible to update those views. But if there were metadata about where the data "came from," there would have to be something in the metadata to indicate that. It would be impractical because it would be complex, and have little value.

Access validation rule violation update query across multiple tables

I would like to create an update query to update a yes/no field in one table (called 'pmh' for past medical history) based on the numeric value of a field in another table (called 'bloods'). I am trying to populate a yes/no field for kidney disease based on a blood test result.
If I do this when both fields are in one table, it works. If I try and do it across two tables, I get a 'Validation rule violation' error message. Apart from being in one or two tables, the fields are exactly the same. There are no validation rules or zerolength criteria in either the tables or fields.
I wonder whether this is something to do with the join type in Relationships. I have set the join type to 2 ('Include ALL records from 'bloods' and only those records from 'pmh' where the joined fields are equal') - because I want to be able to see all patients with a value in the 'bloods' table.
The relationship between the tables is one-to-one - each patient has only one set of blood tests - the reason for not using one table is that the number of fields would be greater than 255.
I hope this makes sense - I have tried to make it as succinct as I can. Thanks everyone for your help, and let me know if you need any more information.
Sounds like data structure is not normalized. Saving calculated data is usually a bad idea. The Y/N value can be calculated when needed.
Join type set in relationships builder should not prevent update. Should provide attempted query for analysis. Is it like:
UPDATE pmh INNER JOIN bloods ON pmh.ID = bloods.ID SET pmh.fieldname = IIf([bloods.fieldname]="something", True, False);

Joining a table stored within a column of the results

I want to try and keep this as one query and not use PHP, but it's proving to be tough.
I have a table called applications, that stores all the applications and some basic information about them.
Then, I have a table with all the types of applications in it, and that table contains a reference to another table which stores more specific data about the specific type of application in question.
select applications.id as appid, applications.category, type.title as type, type.id as tid, type.valuefld, type.tablename
from applications
left join type on applications.typeid=type.id
left join department on type.deptid=department.id
where not isnull(work_cat)
and work_cat != ''
and applications.deleted=0
and datei between '10-04-14' and '11-04-14'
order by type, work_cat
Now, in the old version, there is another query on every single result. Over hundreds of results... that sucks.
This is the query I'd like to integrate so I can get all the data in one result row. (Old is ASP, I'm re-writing it in PHP)
query = "select sum("&adors.fields("valuefld")&") as cost, description from "&adors.fields("tablename")&" where appid = '"&adors.fields("tablename")&"'"
Prepared statements, I'm aware, are the best solution, but for now they are not an option.
You can't do this with a plain SQL query - you need to have a defined set of tables that your query is based on. The fact that your current implementation queries from whatever table is named by tablename from the first result-set means that to get this all in one query, you will have to restructure your data. You have to know what tables you're querying from rather than having it dynamic.
If the reason for these different tables is the different information stored in each requiring different record (column) structures, you might want to look into Key/Value pair storage in a large table. Once you combine the dynamically named ones into a single location you can integrate your two queries together.

Advantage of using Views in MySQL

I've learned that views can be used to create custom "table views" (so to say) that aggregate related data from multiple tables.
My question is: what are the advantages of views? Specifically, let's say I have two tables:
event | eid, typeid, name
eventtype | typeid, max_team_members
Now I create a view:
eventdetails | event.eid, event.name, eventtype.max_team_members
| where event.typeid=eventtype.typeid
Now if I want to maximum number of members allowed in a team for some event, I could:
use the view
do a join query (or maybe a stored procedure).
What would be my advantages/disadvantages in each method?
Another query: if data in table events and eventtypes gets updated, is there any overhead involved in updating the data in the view (considering it caches resultant data)?
A view is not stored separately: when you query a view, the view is replaced with the definition of that view. So and changes to the data in the tables will show up immediately via the view.
In addition to the security feature pointed out earlier:
If you're writing a large number of queries that would perform that join, it factors out that SQL code. Like doing some operations in a function used in several places, it can make your code easier to read/write/debug.
It would also allow you to change how the join is performed in the future in one place. Perhaps a 1-to-many relationship could become a many-to-many relationship, introducing an extra table in the join. Or you may decide to denormalize and include all of the eventtype fields in each event record so that you don't have to join each time (trading space for query execution time).
You could further split tables later, changing it to a 3-way join, and other queries using the view wouldn't have to be rewritten.
You could add new columns to the table(s) and change the view to leave out the new columns so that some older queries using "select *" don't break when you change the table definitions.
You can restrict users to the view instead of the underlying table(s), thereby enhancing security.
Advantages of SQL Views
1). You can save a complex query(a query with join multiple tables) as view to reuse it in simple manners.
In other words, you can change your multi-line query into single-line query.
2). You can hide sensitive data by converting your query into view with new name and can give the access only required columns instead of giving the access of actual table.