Counting rows with condition - sql

My Table looks like something below
Id | Customer_number | Customer_Name | Customer_owner
I want to insert Customer_Number as a sequence specific to Customer_owner
that is 1,2,3,.... for Customer_owner X and 1,2,3,... Customer_owner Y.
To get the Customer_number I can use following SQL
SELECT COUNT(*) FROM Customer where Customer_owner='X'
My question is that are there any performance impact. Specially for a table with 100,000 records.
Are there any better alternatives?

In terms of performance, I would suggest not adding another column to Customers, for various reasons:
The need to update all of owner's A related customers when adding a customer with the owner A, same goes for removing.
Number of clients is Repeated multiple times - taking up more space and thus (generally) slowing execution.
No real usage to link Number of clients to client's owner via another column for a record describing a single customer.
and many more explanations..
The correct normal form would be having 2 tables:
Customers(Cust_id,Cust_name,Cust_Owner_id)
2.a. Owners (Owner_id,Owner_name,NumberOfCustomers)
OR
2.b. Owners (Owner_id,Owner_name) and have NumberOfCustomers be auto calculated upon Querying.
Edit:
Since you want to display all the customers for a single owner, I assume that is your main usage, you should add a cluster index on Cust_Owner_id . Then , when querying, performance would be good since it will have the benefits of clustering according to your desired data.
Read more about clustering here: Clustered Index
Edit 2:
I've just realized your intent via latest comments, but the solution still remains, I would add, specific to your issue, that I don't recommend you should store the number for all of one owner's customers, instead, keep a SUBSCRIBED DATE Column in Customers table, and when querying, decide of the customer number upon display.
If you want however that number to be permanent (any by that the order 1,2,3,..n will probably break, since customers can be removed), simply use the Customer_Id, since it is already unique.

You can calculate Customer_Number on the fly when you need it:
select c.*, row_number() over (partition by Customer_Owner order by id) as CustomerNumber
from Customer c
This is a much safer approach than trying to store and maintain the number, which can be affected by all sorts of updates into the system. Imagine the fun of changing the numbering when an existing record changes it ownership, for instance.

If you only need unique numbering in the UI you could just assign the numbers in the UI. If you go that route you need to make sure you always retrieve customers in the same order, so add an ORDER BY Id, Or, do what Gordon Linoff suggests.

Related

SQL DB structure - Draft orders and consideration of Order ID as identifier

I am upgrading a system for a client which was developed by myself around 10 years ago.
It is a standard (if there can be such a thing, of course) sales / inventory / accounting system.
One of the additions they have asked me about was the ability to create draft orders. As the company has grown, so have the sizes of the orders. They want the ability to begin entering an order for a client and have the option of saving and coming back to it later.
My initial thoughts would be to have an orders table which includes drafts and a field which signified the status (draft / posted). This would prevent duplicating data across an Orders table and a DraftOrders table.
This seems correct to me but of course the OrderId field (auto-increment int) would no longer be a solid identifier for the Order (since a lot of the numbers in between orders may be missing).
The client would ideally like to keep the OrderId as an identifier so is there any solution which would enable this, rather than creating a draft order table?
Many thanks in advance for your help.
Kind regards
If you are to ensure that the identifier has no gaps for taxation purposes, you can not use the PK in the first place. This is because the sequence may have gaps, too. For example, if an INSERT fails due to some constraint violation you lose the reserved sequence number.
In case you do not want to create a separate table, I may suggest adding a new column to store the tax order ID. It will remain NULL for drafts and will be filled programmatically when the order is placed. On the UI you will show this new column and will possibly allow some searching on it (hint: good candidate for an index), yet internally you will still use same FKs as before (for both orders and drafts).

How to increment a Couner column by 1 with each inserted row BUT per each guid

Apologies for the clumsy title feel free to suggest an improvement.
I have a table Records and there's a UserId column that refers to who's made the deposition. There's also Counter column which is identity(1,1) (it's important to keep in mind that it's not same one as the Id column that is the primary key).
The problem got obvious when we started depositing from different accounts, because before, the user could ask for record number 123 through 127, getting 5 amounts but now, their picks might be 123, 125, 126 or even worse - nothing at all.
The only option to handle it as far I can imagine to create a business logic layer that checks for the highest deposition counter for a user and adds the new record with that increased by one.
But it sure would be nice to have it automagically working. Something like identity(1,1,guid). Is it possible?
The only option to handle it as far I can imagine to create a business
logic layer that checks for the highest deposition counter for a user
and adds the new record with that increased by one.
Time to learn.
Add the last given number to the account table.
Use a trigger to assign higher numbers in the insert event of SQL Server.
Finished. This obviously assumes your relational database is used in a relational fashion so the records are related to a user table, not just holding a user id (which would be a terrible design).
If not, you can also maintain a table of all seen GUID's by means of said trigger.
To maintain such a column, you would need a trigger.
You might consider calculating the value when you query the table:
select r.*, row_number() over (partition by guid order by id) as seqnum
from records r;

Indexed View with its own rowversion for Azure Search indexer

I'm trying to design the best way to index my data into Azure Search. Let's say my Azure SQL Database contains two tables:
products
orders
In my Azure Search index I want to have not only products (name, category, description etc.), but also count of orders for this product (to use this in the scoring profiles, to boost popular products in search results).
I think that the best way to do this is to create a view (indexed view?) which will contain columns from products and count of orders for each product, but I'm not sure if my view (indexed view?) can have its own rowversion column, which will change every time the count changes (orders may be withdrawn - DELETED - and placed - INSERTED).
Maybe there is some easier solution to my problem? Any hints are appreciated.
Regards,
MJ
Yes, I believe the way you are looking to do this is a good approach. Some other things that I have seen people do is to also includes types For example, you could have a Collection field (which is an Array of strings), perhaps called OrderTypes that you would load with all of the associated order types for that product. That way you can use the Azure Search $facets features to show you the total count of specific order types. Also, you can use this to drill into the specifics of those order. For example, you could then filter based on the selected order type they selected. Certainly if there are too many types of Orders, perhaps that might not be viable.
In any case, yes, I think this would work well and also don't forget, if you want to periodically update this count you could simply pass on just that value (rather than sending the whole product fields) to make it more efficient.
A view cannot have its "own" rowversion column - that column should come from either products or orders table. If you make that column indexed, a high water mark change tracking policy will be able to capture new or updated (but not deleted) rows efficiently. If products are deleted, you should look into using a soft-delete approach as described in http://azure.microsoft.com/en-us/documentation/articles/search-howto-connecting-azure-sql-database-to-azure-search-using-indexers-2015-02-28/
HTH,
Eugene

Changelog for a table

I want to design a changelog for a few tables. Lets call it table restaurant. Every time a user modifies the list of restaurants the change should be logged.
Idea 1
My first idea was to create 2 tables. One which contains all the restaurants RESTAURANT_VALUE (restaurantId*, restaurantValueId*, address, phone, ..., username, insertDate). Every time a change is made it creates a new entry. Then a table RESTAURANT (restaurantId*, restaurantValueId) which will link to the current valid restaurantValueId. So one table that holds the current and the previous version.
Idea 2
It starts with 2 tables as well. One of them contains all current restaurants. e.g. RESTAURANT_CURRENT. And a second table which contains all changes RESTAURANT_HISTORY. Therefore both need to have the exactly same columns. Every time a change occurs the values of the 'current' table are copied into the history table, and the new version in the 'current'.
My opinion
Idea 1 doesn't care if columns will ever be added or not, therefore maintenance and adding of columns would be easy. However, I think as the database grows... wouldn't it slow down? Idea 2 has the advantage that the table with the values will never have any 'old' stuff and not get crowded.
Theoretically I think Idea 1 should be the one done
What do you think. Would you go for Idea 1 or another one? Are there any other important practical thoughts I am not aware of?
The approach strongly depends on your needs. Why would you want a history table?
If it's just for auditing purposes, then make a separate restaurant_history table (idea 2) to keep the history aside. If you want to present the history in the application, then go for signle restaurants table with one of below options:
seq_no - record version number incrementing with each update. If you need current data, you must search for highest seq_no for given restaurant_id(s), so optionally use also current marker, allowing straighforward current = true
valid_from, valid_to - where valid_to is NULL for current record
Sometimes there is need to query efficiently which attributes exactly changed. to do this easily you can consider a history table on attribute level: (restaurant_id, attribute, old_value, new_value, change_date, user).

Database Design: Stored Record Edit History (Temporal Data)

I want to store temporal information in a database. I have come up with the design below. Is this the best way to do it?
MasterTable
ID
DetailsTable
ID
MasterTableID
CreatedOn
Title
Content
While it works for my purposes having a MasterTable with just an ID field just does not feel right however I can see no other way to link the Details records together.
Is there a cleaner / standard way to do this?
An idea would be to design 2 tables as follows:
Entity table: EntityId - PK, Title, Content
EntityHistory table: EntityId - PK, Version - PK, CreatedOn, Title, Content
Some thoughts about:
Usually you'll need to work only with current version of your row, so your queries will not take into account previous versions while you're joining data, etc. On long term premise, this could have a huge impact on performance, statistics will not be accurate, data selectivity can negatively impact index selection, etc.
In case you work often with current values and historical value, you can define a view as a union on both 2 tables.
How to manage adding a new version? Within a transaction, copy the values from Entity in EntityHistory (by increasing version), then update Entity row with new values. Or alternatively, you could define a trigger on Entity table that will do trick behind.
Use a rowversion column: http://technet.microsoft.com/en-us/library/ms182776(v=sql.105).aspx
Just leave out the MasterTable.
Rows in your DetailsTable will still be "linked together", as you call it, by having the same ID column value.
Any other kind of useful "linking" you might want to do (e.g. link a row to its immediate successor or predecessor) is not achieved by having that MasterTable anyway. It achieves nothing (Unless you would want to have ID's in it, for which there is no Details, such that the ID never has been created, which seems rather unlikely). Leave it out.