I am currently working with a bitemporal application, which stores data entries using 4 timestamps:
Valid_from, Valid_to
Registration_from, Registration_to
The first two state when the given entry is valid_from and valid_to,
and the other two are when the entry has been registered_from,
and assumed as true until registration_to.
In this time setting I need to make sure that each row has unique column within the same valid_from and valid_to known within the same registration_from and registration_to across multiple entries.
So I need to check every row before insertion (pseudo-code):
If registration period is overlapping
If Valid period is overlapping
Check if properties are the same
Throw error if they are
I have tried with an exclusion like this:
ADD Constraint exclusion_reg_{entity.InternalName}_registration_{string.Join('_', listOfAttributes)}_key Exclude using gist({string.Join(',', listOfAttributes.Select(x => x + " with =").ToList())} , registration WITH &&);
But I am not sure whether I am using it correctly. I am currently always getting an error, since the check is done in opposite order, and among the incorrect ones. Is there a way to make this exclusion check nested, such that it only check validation overlap if the registration is overlapping, and throws an error if this is true?
How do I go about that in PostreSQL?
Just list both ranges in the exclusion constraint.
ALTER TABLE tbl ADD CONSTRAINT foo
EXCLUDE USING gist (attribute_1 WITH =, attribute_2 WITH = -- more?
, tsrange(valid_from, valid_to) WITH &&
, tsrange(registration_from, registration_to) WITH &&);
It should be safe to assume that essential basics are clear after I answered your related (simpler) question with more explanation a couple of weeks ago. Others may want to read this first:
How to ensure entries with non-overlapping time ranges?
To enforce your constraint, the order of expressions doesn't even matter. Consider the basic definition in the manual of how exclusion constraints operate:
Exclusion constraints ensure that if any two rows are compared on the
specified columns or expressions using the specified operators, at least one of these operator comparisons will return false or null.
This effectively enforces your constraint: only if all expressions evaluate to true, in other words, both ranges overlap and all attributes match exactly, the constraint raises an exception.
However, since the constraint is implemented with the use of a corresponding multicolumn GiST index, the order of expressions matters for performance after all. The manual:
A multicolumn GiST index can be used with query conditions that
involve any subset of the index's columns. Conditions on additional
columns restrict the entries returned by the index, but the condition
on the first column is the most important one for determining how much
of the index needs to be scanned. A GiST index will be relatively
ineffective if its first column has only a few distinct values, even
if there are many distinct values in additional columns.
So rearrange expressions to place the ones with the most distinct values in the column first.
Related
Hypothetically, I have two SQL tables: Table and AuditTable. In Table is a column, org_id, of type float with nulls allowed. Also, org_id is not a primary key. A column with the same name resides in AuditTable. I also have an EditTable class used to make changes to Table and AuditTable. The members of EditTable are set via a user interface. EditTable also contains a org_id member.
There is no good reason why Table.org_id was made a float; it will always contain an integer value. However, since Table was already existing, I can't change the type of Table.org_id. However, since I created AuditTable and EditTable I can set AuditTable.org_id and EditTable.org_id to any type.
When Visual Studio converts Table into a C# class, Table.org_id is made a Nullable<double>. Should I make AuditTable.org_id a float with nulls allowed and make EditTable.org_id a nullable double to match Table.org_id? Or should I make both AuditTable.org_id and EditTable.org_id ints and then do some casting? However, I was thinking about staying away from casting to be on the safe side and just make the types match the orginal Table.
Thanks for any suggestions.
Oh, it is a bad idea to store join keys as floating point numbers. I wish that SQL actually banned this practice. The issue is that 0.9999999999 might look like 1.00000000, but they don't match when joining (or in a where clause). Much better to have what-you-see-is-what-you-get for such conditions.
First, go to whoever you can and beg/bribe/flatter/encourage them to do:
alter table `table` modify org_id int;
If that doesn't work, you have a conundrum. It is much better for query performance to have join keys be of the same types, even types that I don't agree with. Also, that is a pretty important concept for databases. So, you cannot change that join key.
Instead, I think you should add a new key into your table, called something like org_id_int. This would have the correct type, a useful index -- everything except a pretty name. Use this for your joins. Use the other key for the joins to the existing table, until it gets fixed.
I want to solve problem. I trying to do algorithm, where I can building a queries. For example If I have 1 or 2 condition I can construct my algorithm on programming switches with string format. (pic. 1)
But if I want more than 2 conditions, I'll be have a lot variants.(pic. 2)
I want just SELECT with different conditions from database.
Maybe someone know what way I should to use to construct a lot different conditions?
As long as they're always querying/filtering the same denormalized set, you can write a WHERE clause builder, but you'll need to treat each field/operator/value and clause independently.
Each value in your field combo box should correspond to one table.field name in the set, each value in your operator combo box corresponds to SQL operators to add to the clause, and you'll have problems with your values they enter because you'll need to distinguish between numbers and strings, formatted without or with single quotes. Also, there's date formats to consider.
You may also get people making combinations of fields and operators that don't make sense. 'After' makes sense for dates, but not email addresses. Consider limiting your choices in the operator combo by the data type of the field selection.
I have an application which has rows of data in a relation database the table needs a status which will always be either
Not Submitted, Awaiting Approval, Approved, Rejected
Now since these will never change I was trying to decide the best way to implement them I can either think of a Status enum with the values and an int assigned where the int is placed into the status column on the table row.
Or a status table that linked to the table and the user select one of these as the current status.
I can't decide which is the better option as I currently have a enum in place with these values for the approval pages to populate the dropdown etc and setup the sql (as it currently using to bool Approved and submitted for approval but this is dirty for various reasons and needs changed).
Wondering what your thought on this were and whether I should go for one or the other.
If it makes any difference I am using Entity framework.
I would go with the Enum if it never changes since this will be more performant (no join to get the status). Also, it's the simpler solution :).
Now since these will never change...
You can count on this assumption being false, and sooner than you think.
I would use a lookup table. It's far easier to add or change values in a lookup table than to change the definition of an enum.
You can use a natural primary key in the lookup table so you don't need to do a join to get the value. Yes a string takes a bit more space than an integer id, but if your goal is to avoid the join this will accomplish that goal.
I use Enums and use the [Description("asdf")] attribute to bind meaningful sentences or other things that aren't allowed in Enums. Then use the Enum text itself as a value in drop downs and the Description as the visible text.
I am inserting a column in a DataGridView programmatically (i.e., not bound to any data tables/databases) as follows:
int lastIndex = m_DGV.Columns.Count - 1; // Count = 4 in this case
DataGridViewTextBoxColumn col = (DataGridViewTextBoxColumn)m_DGV.Columns[lastIndex];
m_DGV.Columns.RemoveAt(lastIndex);
m_DGV.Columns.Insert(insertIndex, col); // insertIndex = 2
I have found that my columns are visually out of order sometimes using this method. A workaround is to manually set the DisplayIndex property of the column afterwards. Adding this code "fixes it", but I don't understand why it behaves this way.
Console.Write(m_DGV.Columns[0].DisplayIndex); // Has value of 0
Console.Write(m_DGV.Columns[1].DisplayIndex); // Has value of 1
Console.Write(m_DGV.Columns[2].DisplayIndex); // Has value of 3
Console.Write(m_DGV.Columns[3].DisplayIndex); // Has value of 2
col.DisplayIndex = insertIndex;
Console.Write(m_DGV.Columns[0].DisplayIndex); // Has value of 0
Console.Write(m_DGV.Columns[1].DisplayIndex); // Has value of 1
Console.Write(m_DGV.Columns[2].DisplayIndex); // Has value of 2
Console.Write(m_DGV.Columns[3].DisplayIndex); // Has value of 3
As an aside, my grid can grow its column count dynamically. I wanted to grow it in chunks, so each insert didn't require a column allocation (and associated initialization). Each "new" column would then be added by grabbing an unused column from the end, inserting it into the desired position, and making it visible.
I suspect this is because the order of the columns in the DataGridView do not necessarily dictate the display order, though without explicitly being assigned by default the order of the columns dictate the DisplayIndex property values. That is why there is a DisplayIndex property, so you may add columns to the collection without performing Inserts - you just need to specify the DisplayIndex value and a cascade update occurs for everything with an equal or greater DisplayIndex. It appears from your example the inserted column is also receiving the first skipped DisplayIndex value.
From a question/answer I found:
Changing the DisplayIndex will cause
all the columns between the old
DisplayIndex and the new DisplayIndex
to be shifted.
As with nearly all collections (other than LinkedLists) its always better to add to a collection than insert into a collection. The behavior you are seeing is a reflection of that rule.
I have a couple of ideas.
How about addressing your columns by a unique name, rather than the index in the collection? They might not already have a name, but you could keep track of who's who if you gave them a name that meant something.
You can use the GetFirstColumn, GetNextColumn, GetPreviousColumn, GetLastColumn methods of the DataGridViewColumnCollection class, which work on display order, not the order in the collection. You can also just iterate through the collection using a for loop and m_DGV.Columns[i] until you find the one you want.
Create an inherited DataGridView and DataGridViewColumnCollection. The DataGridView simply is overridden to use your new collection class. Your new DataGridViewColumnCollection will include a method to address the collection by display index, presumably by iterating through the collection until you find the one you want (see #2). Or you can save a dictionary and keep it updated for very large numbers of columns.
I doubt the performance increase of keeping a dictionary, since every time a column moves, you essentially have to rewrite the entire thing. Iterating through is O(n) anyway, and unless you're talking asynchronous operations with hundreds of columns, you're probably okay.
You might be able to override the this[] operator as well, assuming it doesn't screw up the DataGridView.
Idea #1 might be the easiest to implement, but not necessarily the prettiest. Idea #2 works, and you can put it in a function DataGridViewColumn GetColumnByDisplayIndex(int Index). Idea #3 is cute, and certainly the most encapsulated approach, but isn't exactly trivial.
Thanks to cfeduke for excellent advice. I suspected Insert would be slower, but the provided link enlightened me on JUST HOW MUCH slower.
This brings up the question of how to efficiently insert and remove columns dynamically on a DataGridView. It looks like the ideal design would be to add plenty of columns using Add or AddRange, and then never really remove them. You could then simulate removal by setting the Visible property to false. And you could insert a column by grabbing an invisible column, setting its DisplayIndex and making it visible.
However, I suspect there would be landmines to avoid with this approach. Foremost being that you can no longer index your data in a straightforward manner. That is, m_DGV.Columns[i] and m_DGV.Rows[n].Cells[i] will not be mapped properly. I suppose you could create a Map/Dictionary to maintain an external intuitive mapping.
Since my application (as currently designed) requires frequent column insertion and removal it might be worth it. Anyone have any suggestions?
I was wondering if anyone has a good solution to a problem I've encountered numerous times during the last years.
I have a shopping cart and my customer explicitly requests that it's order is significant. So I need to persist the order to the DB.
The obvious way would be to simply insert some OrderField where I would assign the number 0 to N and sort it that way.
But doing so would make reordering harder and I somehow feel that this solution is kinda fragile and will come back at me some day.
(I use C# 3,5 with NHibernate and SQL Server 2005)
Thank you
Ok here is my solution to make programming this easier for anyone that happens along to this thread. the trick is being able to update all the order indexes above or below an insert / deletion in one update.
Using a numeric (integer) column in your table, supported by the SQL queries
CREATE TABLE myitems (Myitem TEXT, id INTEGER PRIMARY KEY, orderindex NUMERIC);
To delete the item at orderindex 6:
DELETE FROM myitems WHERE orderindex=6;
UPDATE myitems SET orderindex = (orderindex - 1) WHERE orderindex > 6;
To swap two items (4 and 7):
UPDATE myitems SET orderindex = 0 WHERE orderindex = 4;
UPDATE myitems SET orderindex = 4 WHERE orderindex = 7;
UPDATE myitems SET orderindex = 7 WHERE orderindex = 0;
i.e. 0 is not used, so use a it as a dummy to avoid having an ambiguous item.
To insert at 3:
UPDATE myitems SET orderindex = (orderindex + 1) WHERE orderindex > 2;
INSERT INTO myitems (Myitem,orderindex) values ("MytxtitemHere",3)
Best solution is a Doubly Linked list. O(1) for all operations except indexing. Nothing can index SQL quickly though except a where clause on the item you want.
0,10,20 types fail. Sequence column ones fail. Float sequence column fails at group moves.
Doubly Linked list is same operations for addition, removal, group deletion, group addition, group move. Single linked list works ok too. Double linked is better with SQL in my opinion though. Single linked list requires you to have the entire list.
FWIW, I think the way you suggest (i.e. committing the order to the database) is not a bad solution to your problem. I also think it's probably the safest/most reliable way.
How about using a linked list implementation? Having one column the will hold the value (order number) of the next item. I think it's by far the easiest to use when doing insertion of orders in between. No need to renumber.
Unfortunately there is no magic bullet for this. You cannot guarentee the order of any SELECT statement WITHOUT an order by clause. You need to add the column and program around it.
I don't know that I'd recommend adding gaps in the order sequence, depending on the size of your lists and the hits on the site, you might gain very little for the over head of handling the logic (you'd still need to cater for the occasion where all the gaps have been used up). I'd take a close look to see what benifits this would give you in your situation.
Sorry I can't offer anything better, Hope this helped.
I wouldn't recommend the A, AA, B, BA, BB approach at all. There's a lot of extra processing involved to determine hierarchy and inserting entries in between is not fun at all.
Just add an OrderField, integer. Don't use gaps, because then you have to either work with a non-standard 'step' on your next middle insert, or you will have to resynchronize your list first, then add a new entry.
Having 0...N is easy to reorder, and if you can use Array methods or List methods outside of SQL to re-order the collection as a whole, then update each entry, or you can figure out where you are inserting into, and +1 or -1 each entry after or before it accordingly.
Once you have a little library written for it, it'll be a piece of cake.
I would just insert an order field. Its the simplest way. If the customer can reorder the fields or you need to insert in the middle then just rewrite the order fields for all items in that batch.
If down the line you find this limiting due to poor performance on inserts and updates then it is possible to use a varchar field rather than an integer. This allows for quite a high level of precision when inserting. eg to insert between items 'A' and 'B' you can insert an item ordered as 'AA'. This is almost certainly overkill for a shopping cart though.
On a level of abstraction above the cart Items let's say CartOrder (that has 1-n with CartItem) you can maintain a field called itemOrder which could be just a comma - separated list of id(PK) of cartItem records relevant . It will be at application layer that you require to parse that and arrange your item models accordingly . The big plus for this approach will be in case of order reshufflings , there might not be changes on individual objects but since order is persisted as an index field inside the order item table rows you will have to issue an update command for each one of the rows updating their index field.
Please let me know your criticisms on this approach, i am curious to know in which ways this might fail.
I solved it pragmatically like this:
The order is defined in the UI.
The backend gets a POST request that contains the IDs and the corresponding Position of every item in the list.
I start a transaction and update the position for every ID.
Done.
So ordering is expensive but reading the ordered list is super cheap.
I would recommend keeping gaps in the order number, so instead of 1,2,3 etc, use 10,20,30... If you need to just insert one more item, you could put it at 15, rather than reordering everything at that point.
Well, I would say the short answer is:
Create a primary key of autoidentity in the cartcontents table, then insert rows in the correct top-down order. Then by selecting from the table with order by the primary key autoidentity column would give you the same list. By doing this you have to delete all items and reinsert then in case of alterations to the cart contents. (But that is still quite a clean way of doing it) If that's not feasible, then go with the order column like suggested by others.
When I use Hibernate, and need to save the order of a #OneToMany, I use a Map and not a List.
#OneToMany(fetch = FetchType.EAGER, mappedBy = "rule", cascade = CascadeType.ALL)
#MapKey(name = "position")
#OrderBy("position")
private Map<Integer, RuleAction> actions = LazyMap.decorate(new LinkedHashMap<>(), FactoryUtils.instantiateFactory(RuleAction.class, new Class[] { Rule.class }, new Object[] { this }));
In this Java example, position is an Integer property of RuleAction so the order is persisted that way. I guess in C# this would look rather similar.