Database Multiple Optional Filters with Null values in AnyLogic - anylogic

I am trying to find the most optimal way to create conditional filtering of a Database in AnyLogic. The database, looks as follows:
What I am trying to do is adding in AnyLogic Main window 12 check boxes: P1, P2, P3, ..., T5, T6
If the user checks P1, with reference to the above table, A and B need to be displayed.
If the user checks P2, C needs to be displayed
If the user checks P1 and T2, A needs to be discplayed
In summary, it is like filtering in Excel any set of columns by "x" noting that the other cells have a null value.
To start, I used the following code to filter for P1 only (adding the entries to a collection of type String):
collectionDescription.addAll(
selectFrom( data_base ).
where( data_base.P1.eq("x")).
list( data_base.Col1));
Now to filter for P2 as well, the following can be done:
collectionDescription.addAll(
selectFrom( data_base ).
where( data_base.P1.eq("x")).
where( data_base.P2.eq("x")).
list( data_base.Col1));
Following the above logic, as many "where" conditions as needed can be added. However, there are so many possible combinations (e.g. P1/P2, P1/P2/P3, P1/P3, etc. you can imagine the amount of possible combinations).
So, I thought of a potential solution where I would add as many "where" conditions as there are columns, but instead of adding ".eq("x")", I would add ".eq(varP1)". If a checkbox (e.g. P1) is ticked, varP1 would be equal to "x" (varP1 being a variable of type String). But if the box is unticked, ideally varP1 should take a value that means "where anything" so that the condition would not make any impact. I did not manage to find a way to mimic this behavior.
Sorry for the long post, but I wanted to make sure the situation is as clear as possible. So am I on the right track? Any suggestions on how to fix this? Your suggestions would be highly appreciated.

let's say you have a checkbox associated to a variable varP1 to define what you want... then you can do
selectFrom(db_table)
.where(varP1 ? db_table.db_column.eq("x") : db_table.db_column.isNotNull().or(db_table.db_column.isNull()))
.list();
where anything is what i here did as any value which is either null or not null... so if the box is checked then you will find x, otherwise you will find anything

Related

merge features n time

Here is my issue, I'm working on a project of water supply where I have to merge line features representing pipes if they have the same material of construction and if they are touching each other. The merge is done two by two what it means that some features will be duplicated in some cases like described in the figure below :
this shows exactly my issue. After the merge I will get three records but what I want is just one record which encompasses the whole pipes that fill the conditions put in the where clause :
Here is the query that helps me do the merge :
drop table if exists touches_material;
create table touches_material as
select distinct a.*,
st_Union(a.geom,b.geom) as fusion from pipe a, pipe b
where a.id < b.id and a.material = b.material and
st_touches(a.geom,b.geom)
group by a.id,a.geom,b.geom
the following picture picture shows the expected result on a test data, it's realized via QGIS GIS software :
but this is what I' getting with my query :
if you have any idea about how to achieve the aim that I invoked, I would be very thankful to get an answer from you. Best regards.

OrientDB: UPDATE of adjacent vertex

Background
I have a model represented by a graph in OrientDB. The model consists of a few classes, among others A and B. The classes are connected with a relation has as an edge from A to B. The edge also connects A to other classes:
A ---has--> B
A ---has--> C
Problem
I want to update a property of B if it has a has edge to an A with a given RecordID.
My Solution
Currently I am selecting the target/out vertex of all edges has that are of class B starting at a given RecordID. This works but feels like I am missing an easier solution to this.
UPDATE (SELECT expand(out('has')[#class = 'B']) FROM #11:1) SET prop = true
I also tried the following, which did not work as I expected:
UPDATE B SET prop = true WHERE in('has').#rid = #11:1
My Question
Is there a simpler solution than an UPDATE with SUBSELECT?
I don't think there is any premade sql function that does this kind of filtering in an update.
Your first query is the way to go because it traverses instead of filtering on all the vertices. Yes, you have a subquery but it is faster then using a where in the update statement.
It would be cool to have a syntax like this :
update #9:1.inV('edgeClassName')[#class='className'] set prop = true
We have to use a subquery for this to work. It feels natural to me.

Tableau: Create a table calculation that sums distinct string values (names) when condition is met

I am getting my data from denormalized table, where I keep names and actions (apart from other things). I want to create a calculated field that will return sum of workgroup names but only when there are more than five actions present in DB for given workgroup.
Here's how I have done it when I wanted to check if certain action has been registered for workgroup:
WINDOW_SUM(COUNTD(IF [action] = "ADD" THEN [workgroup_name] END))
When I try to do similar thing with count, I am getting "Cannot mix aggregate and non-aggregate arguments":
WINDOW_SUM(COUNTD(IF COUNT([Number of Records]) > 5 THEN [workgroup_name] END))
I know that there's problem with the IF clause, but don't know how to fix it.
How to change the IF to be valid? Maybe there's an easier way to do it, that I am missing?
EDIT:
(after Inox's response)
I know that my problem is mixing aggregate with non-aggregate fields. I can't use filter to do it, because I want to use it later as a part of more complicated view - filtering would destroy the whole idea.
No, the problem is to mix aggregated arguments (e.g., sum, count) with non aggregate ones (e.g., any field directly). And that's what you're doing mixing COUNT([Number of Records]) with [workgroup_name]
If your goal is to know how many workgroup_name (unique) has more than 5 records (seems like that by the idea of your code), I think it's easier to filter then count.
So first you drag workgroup_name to Filter, go to tab conditions, select By field, Number of Records, Count, >, 5
This way you'll filter only the workgroup_name that has more than 5 records.
Now you can go with a simple COUNTD(workgroup_name)
EDIT: After clarification
Okay, than you need to add a marker that is fixed in your database. So table calculations won't help you.
By definition table calculation depends on the fields that are on the worksheet (and how you decide to use those fields to partition or address), and it's only calculated AFTER being called in a sheet. That way, each time you call the function it will recalculate, and for some analysis you may want to do, the fields you need to make the table calculation correct won't be there.
Same thing applies to aggregations (counts, sums,...), the aggregation depends, well, on the level of aggregation you have.
In this case it's better that you manipulate your data prior to connecting it to Tableau. I don't see a direct way (a single calculated field that would solve your problem). What can be done is to generate a db from Tableau (with the aggregation of number of records for each workgroup_name) then export it to csv or mdb and then reconnect it to Tableau. But if you can manipulate your database outside Tableau, it's usually a better solution

Merge neo4j relationships into one while returning the result if certain condition satisfies

My use case is:
I have to return whole graph in result but the condition is
If there are more than 1 relationship in between two particular nodes in the same direction then I have to just merge it into 1 relationship. For ex: Lets say there are two nodes 'm' and 'n' and there are 3 relations in between these nodes say r1, r2, r3 (in the same direction) then when I get the result after firing cypher query I should get only 1 relation in between 'n' and 'm'.
I need to perform some operations on top of it like the resultant relation that we got from merging all the relations should contain the properties and their values that I want to retain. Actually I will retain all the properties of any one of the relations that are merging depending upon the timestamp field that is one of the properties in relation.
Note : I have same properties throughout all my relations (The number of properties and name of properties are same across all relations. Values may differ for sure)
Any help would be appreciated. Thanks in advance.
You mean something like this?
Delete all except the first
MATCH (a)-[r]->(b)
WITH a,b,type(r) as type, collect(r) as rels
FOREACH (r in rels[1..] | DELETE r)
Ordering by timestamp first
MATCH (a)-[r]->(b)
WITH a,r,b
ORDER BY r.timestamp DESC
WITH a,b,type(r) as type, collect(r) as rels
FOREACH (r in rels[1..] | DELETE r)
If you want to do all those operations virtually just on query results you'd do them in your programming language of choice.

How to do a SQL query using columns from a related table?

I've got three related SQL tables, simplified they look like this:
ShopTable
[ShopID]
ShelfTable
[ShelfID]
[ShopID]
InventoryTable
[ShelfID]
[Value]
[ShopID] and [ShelfID] are relations. Now what I want to do is get the SUM of [Value] for one [ShopID], but this obviously won't work since [ShopID] ain't part of InventoryTable:
SELECT SUM([Value]) WHERE [ShopID] = '1'
How do I have to write the query to filter the InventoryTable using the ShopID?
SELECT SUM(i.value)
FROM shelfTable s
JOIN inventoryTable i
ON i.shelfId = s.shelfId
WHERE s.shopId = 1
This is a fundamental question about relations between tables, so I'll provide some detail, hoping that you can use some of these ideas when writing SQL queries in the future.
Let's start with one basic thing first. [ShopID] could refer to two different but related columns, one in [ShopTable] and one in [ShelfTable]. The same things applies to [ShelfID]. It's useful to always specify the table.
You describe [ShopID] and [ShelfID] as "relations." As Damien_The_Unbeliever has commented, those columns are, in fact, two pairs of primary and foreign keys. That is, [ShelfTable].[ShelfID] identifies a "shelf" record, and [InventoryTable].[ShelfID] relates an "inventory item" (whatever that is) to a "shelf." (It's not always possible to interpret rows in a database this naively, but I'm willing to guess I'm not too far off from reality.)
Likewise, each "shelf" belongs to one "shop," and [ShelfTable].[ShopID] refers to that specific "shop." Notice that because we have the value of [ShopID] already (I'll call it "#MyShopID"), we don't even need the [ShopTable] here. We can just use [ShelfTable].[ShopID] to filter for the "shelves" we're interested in.
You're asking to get the sum total of [InventoryTable].[Value] for one [ShopID] value, but [ShopID] doesn't show up in [InventoryTable]. That's where your (inner) join comes into play. You know that you'll be adding up values from [InventoryTable], but you've got to specify the particular "shop." You specify #MyShopID for [ShelfTable].[ShelfID], which will do your filtering in [InventoryTable] for you.
One final thing before composing the query. I'm assuming that you haven't oversimplified your tables too much, and that [Value] is the total value of each "inventory item," and not just a unit value. If it wasn't, we'd have to multiply values by quantities, etc., but I'll let you check your own work here.
So, here's what we do:
We select FROM the [InventoryTable]
but we INNER JOIN to the [ShelfTable] on [ShelfID] from both tables
and we only want "shelves" from one "shop," i.e. WHERE [ShelfTable].[ShopID] = #MyShopID
and then we SELECT the SUM([InventoryTable].[Value])
and we're done. In SQL, let's remove the brackets, provide some table aliases, and we'll get a query that looks like this:
SELECT SUM(inv.Value)
FROM InventoryTable AS inv
INNER JOIN ShelfTable AS shf ON shf.ShelfID = inv.ShelfID
WHERE shf.ShopID = #MyShopID
;
Here are a few take-away points to consider. Notice we handled the FROM clause first. You'll always want to do that.
You'll also want a "driving table" to start with, in this case, [InventoryTable]. The other tables in your join add extra information and provide you a means to filter, but don't otherwise interfere with your summing up. More complex queries don't offer such an obvious luxury, but we're not getting too fancy here.
You'll also note, just briefly, that because [ShelfID] is a primary key in [ShelfTable], those [ShelfID]'s are unique values in [ShelfTable], and so each "inventory" thing belongs to a single "shelf." So the join won't cause us to double-count values. That's a good thing to remember when you're not dealing with primary and foreign keys, like we're doing here.
Hope that helps. And I hope I didn't come across as too pedantic.