Save and get arbitrary sort order in SQL Server - sql-server-2008

My client wants to sort products by drag & drop. The drag & drop part is easy with javascript.
My problem is how do I save and get the sort order?
I'm using .net c# and SQL Server 2008.
When I move a product and drop it in a new position I get the id of the product that's moved, product in front and product behind. With this data I want to update the sort order of products.
I was thinking of adding a field with position, but then I guess I have to update every item when position changes.

In general adding an additional position field is the only thing you can do, to get truly arbitrary ordering.
But you can implement it in several ways. Here are two ways I've implemented myself some time ago.
1. Method: Update all position values, by looping over your items and performing an UPDATE statement for every position.
This is easy to implement, but because of the many updates, it's not good for many items and/or large tables. Especially if you do it via Ajax and perform a complete re-ordering on every change in the list.
2. Method: Do a smart update of only the affected rows.
SELECT all items in the current sort order (The "old list") (Usually fast compared to an UPDATE statement)
Iterate over all items from the "new list" and compare each item to the item from the old list at the same position/index. If the items are the same, don't do anything
If the items are different find that item from the old list, which should actually be at that position and update its position value accordingly (Some lookup data structure might be useful here)
That way you only have to perform minimal database updates, but you'll have more complex code.
Personally I'd go with the first way, until the database updates actually become a performance problem.

We have a sort column but yes we have to re-index all rows as things change. You could mitigate this by assigning sort's in large enough increments to allow some level of movability before you have to do this, such as in 10's or 100's but that's not the best solution and I'd be interested to see what other ideas people have.

If you can capture each move programatically (with up and down buttons for example) then you can just swap the position numbers of the row moving and the row being moved. Make sure that you add new rows at the max position + 1.

Related

Sql delete thousands of rows with text file

I have a database that has a few tables with over 150,000 rows. I want to delete all but about 18,000.
My plan is to go through and obtain the Id of every item I need to keep. I have a list but some names might not match so I plan on manually documenting the ids that I need to keep in a text file. Is there a way I can use said text file to delete everything but the IDs in this text file? Is there a better way?
Backstory: I'm running a game server eq emulator and was able to acquire a list of all items in the game up the expansions I want from the game wiki. But the emulator was written years into the release so items are not in order. I need to get rid of many items on this list of ids and I need to do this in multiple tables.
I tried searching the internet for like situations and saw references to using a list to complete the task. Now my goal is generating a list of items to keep because it is a lot smaller than the items I need to remove.
Alter the table(s) to add column named something like ToDelete. Then you can start updating this column to target your desired rows, and can do it across potentially many steps. Finally, you can run one short DELETE query to remove every targeted row by targeting the new column in the WHERE clause.
I would also be inclined to rename or copy the tables first, to preserve the data in the existing database for quick recovery of rows anywhere you make a mistake.

MySQL query performance for paginating

Ok, so what is the best practice when it comes down to paginating in mysql. Let me make it more clear, let's say that a given time I have 2000 records and there are more being inserted. And I am displaying 25 at a time, I know I have to use limit to paginate through the records. But what am I supposed to do for the total count of my records? Do I count the records every time users click to request the next 25 records. Please, don't tell me the answer straight up but rather point me in the right direction. Thanks!
The simplest solution would be to just continue working with the result set normally as new records are inserted. Presumably, each page you display will use a query looking something like the following:
SELECT *
FROM yourTable
ORDER BY someCol
LIMIT 25
OFFSET 100
As the user pages back and forth, if new data were to come in it is possible that a page could change from what it was previously. From a logical point of view, this isn't so bad. For example, if you had an alphabetical list of products and a new product appeared, then the user would receive this information in a fairly nice way.
As for counting, your code can allow moving to the next page so long as data is there to support a new page being added. Having new records added might mean more pages required to cover the entire table, but it should not affect your logic used to determine when to stop allowing pages.
If your table has a date or timestamp column representing when a record was added, then you might actually be able to restrict the entire result set to a snapshot in time. In this case, you could prevent new data from entering over a given session.
3 sugggestions
1. Only refreshing the data grid, while clicking the next button via ajax (or) storing the count in session for the search parameters opted .
2. Using memcache which is advanced, can be shared across all the users. Generate a unique key based on the filter parameters and keep the count. So you won't hit the data base. When a new record, gets added then you need to clear the existing memcache key. This requires a memache to be running.
3. Create a indexing and if you hit the db for getting the count alone. There won't be much any impact on performance.

Editing table row data populated with with classic asp

I'm hoping this will be a rather simple question to answer, as I'm not looking for any specific code. I have a table on a classic asp page populated from an sql server. I've just set the table up so that each row is clickable and takes you to a page to edit the data in the row. My question is this: Would I be better off trying to use the recordset that populated the table or should I reconnect to the db and pull just the record I want edited.
As always; It Depends. It depends on what you need to edit about the record. It depends on How far apart your DB and site are from each other. It depends on which machine, if the DB and site are on separate machines, is more powerful.
That being said, you should make a new call for that specific record. The reason mainly being because of a specification you made in your question:
...and takes you to a page to edit the data in the row
You should not try to pass a record set between pages. There are a few reasons for this
Only collect what you need
Make sure data is fresh
Consider how your program will scale
On point 1 there are two ways to look at this. One is that you are trying to pass the entire record set across a page when you only need 1 record. There are few situations where another DB call would cost more than this. The other is you are only passing one record which would make me question your design. Why does this record set have every item related to a record. You are selecting way too much for just a result list. Or if the record is that small then Why do you need the new page. Why can you not just reveal an edit template for the item if it is that minimal.
On point 2 consider the following scenario. You are discussing with a coworker how you need to change a customer's record. You pull up this result set in an application but then nature calls and you step away from you desk. The coworker gets called by the customer and asked why the record is not updated yet. To placate the customer your coworker makes the changes. Now you are using an old record set and may overwrite additional changes your coworker made while you were away. This all happens because you never update the record set, you always just pass the old one from page to page.
On point 3 we can look back a point 1 a bit. let us say that you are passing 5 fields now. You decide though that you need a comments field to attach to one of your existing fields. do you intend to pass 2000 characters of that comment field to the next page? How about if each of the 5 need a comment field? Do you intend to pass 10,000 characters for a properly paged record set of 10? do you not do record set paging and need to pass 10,000 characters for a full 126 records.
There are more reasons too. Will you be able to keep your records secure passing them this way? Will this effect your user's experience because they have a crummy computer and cannot build that quick of a post request quickly? Generally it is better to only keep what you need and in most situations your result set should not have everything you need to edit.

mysql adjust value temporarily. Is this possible?

I have a module on my website which lists products by their popularity and the list changes quite regularly. I'd like to automatically discount the top 3 popular products, this is easily done through changing the discount column to 5 for the 3rd product 10 for the 2nd and 15 for the top. However, as the list is regularly changing I need this discount id to revert back to whatever it was before it was overwritten with the new discount id.
Would I have to create another column and call it something like old_discount and transfer the old discount to that before changing the new one and then have it copy it back when it is not longer in the top 3?
I'm hoping someone has an easier way this might be done, any help at all would be appreciated. Thanks for your time.
There's probably no way to get around adding something to manage the top three discounts. As far as actual implementation, there's a couple of ways you could do this that come to mind:
Create a table just to store the current list of top 3 products (or a one-row table with three fields for the top three). Refresh this table with the top 3 when you automatically check. Then in your code that calculates prices, reference this table first to see what is being discounted before doing the rest of the calculation.
If you are going to add a column to the table, I would add a temp_discount instead of old_discount so you can always leave the original alone. Then your code should check if temp_discount is set, use that, otherwise use the normal discount column. Then you simply set temp_discount to 0 before setting the next top 3 products every time you want to refresh.

Ordering records with e.g. drag& drop, how does that look in a clean way?

I have no clue how to achieve this, I tried for hours now. I implemented a drag&drop of a list and now I want to save the change of the order in my db. I think for this is an order field needed which stores an int. But the problem is: how should I populate this field?
E.g. I want to do an operation like "insert a new list item after item at position 2", i would define a value higher than that of position 2 and lower than that of position three. But this is limited somehow.
An idea was to write new order values for each record when changing one to keep a clean order value. But that seems odd because it is slow as hell.
How do good systems solve this problem?
I hope, this is what you want
http://www.ajaxprojects.com/ajax/tutorialdetails.php?itemid=462