Update table increment field - sql

using SQL server 2008.
Hi guys got this query here:
CREATE PROCEDURE [dbo].[GenerateNumbers]
#pg varchar(255)
AS
BEGIN
DECLARE #Counter as int
SET #Counter = 0
UPDATE dbo.paretoMain
SET #counter = NewPareto = #counter +1
WHERE PG = #pg
END
Works fine, only i want it to do this by a particular order of 1 column. basically order by column 1.
cant seem to figure out how though any ideas?
thanks guys!
EDIT:
Ok seems I've confused people so here goes.
3 columns in a table. 1 called "newpareto" 1 called "Sales" 1 called "part".
Sales has currency, part is varchar. Newpareto is blank.
I want to simply 100 numbers for 100 records (example), so when row1, Newpareto = 1.
This query i provided does this.
However. The 100 Records are not sorted. What i need is To somehow add order by in there to order by Sales column so that the top Sales (example £100.00) will be number 1 in the Newpareto column.
Any clearer?

I believe this may be what you are trying to do:
update paretoMain
set NewPareto=rn
from (select Sales, row_number() over(order by Sales desc) as rn from paretoMain) as x
where paretoMain.Sales=x.Sales

Related

SQL: Is there a way to sort a list of rows in a table numerically without adding a new column?

I want to order a list of rows in a table numerically without adding a new column to the table so that the column isn't altered. The new list I want to order numerically is based on some constraints I set on the data I selected.
Ex:
Number Title Year
1 Movie 2016
2 Movie 1983
3 Movie 2000
and so on.
I've tried using ORDER BY, but in order to do so there needs to be a new column to order it by. Can anyone help me with this? Thanks.
Edit #1: In case it's unclear, I want to add in the number 1, 2, 3 and so on (a number increasing numerically for each movie) without adding a new column to the table.
Edit #2: I'm using Toad as my database. Sorry for the lack of clarity, this is one of my first questions. Thanks!
In sqlserver you could use
select ROW_NUMBER() OVER() , title, year
from my_table
in mysql you could add row num this way
set #row = 0;
select #row := #row+1, title, year
from your_table
In Oracle you can use rownum
select rownum, title, year
from your_table
I found the answer, I just need to use COUNT(). Thanks for your contributions.
If the issue is that you do not want to add this column to the existing table have you considered importing the data into a temporary table and assigning some kind of index?
//Add this to drop the table in case it already exists
IF(OBJECT_ID('TEMPDB..#TEMP_TABLE') IS NOT NULL)
BEGIN
DROP TABLE #TEMP_TABLE
END
DECLARE #NUMBER INT = 0
SELECT TITLE, YEAR, #NUMBER AS [KEY] INTO #TEMP_TABLE FROM YOUR_TABLE
UPDATE #TEMP_TABLE
SET #NUMBER = #NUMBER + 1,
[KEY] = [KEY] + #NUMBER
SELECT * FROM #TEMP_TABLE

SQL how to show the page of results that includes a specific record

I have an SQL database, and I use pagination and sorting to show it.
e.g.
SELECT *
FROM People_Table
WHERE Country=#Country
ORDER BY Postcode OFFSET #Offset ROWS FETCH NEXT 12 ROWS ONLY
If a new person is added, I want to show the page of results which contains the new person. They might be halfway down that page, so I don't want to just find them and the next 11 records. Any ideas on how to do this elegantly?
If I understand the question correctly what I'm thinking is you'd need to include a calculated column to contain page number that is based on an NTILE grouping that is based on the order by. Something like this using a partition over clause with an NTILE. See link for details on NTILE.
DECLARE #RowsPerPage INT = 12;
DECLARE #PageCount INT;
SELECT #PageCount = COUNT(*) / #RowsPerPage
FROM People_Table
WHERE Country = #Country;
SELECT * ,
NTILE(#PageCount) OVER ( ORDER BY PostCode ) AS PageNum
FROM People_Table
WHERE Country = #Country
ORDER BY Postcode
OFFSET #Offset ROWS FETCH NEXT #RowsPerPage ROWS ONLY;
Code sample for reference only, I haven't tested it other than making sure it would parse.
Comments: You'd probably need to be more specific on your order by however as ordering by postal code doesn't guarantee the order of rows that share the same postal code. This would be a problem when one postal code starts spanning more than one page. So you want to order by postal code and by person name or something more specific.
Thanks NTILE I'll give that a go. (The postcode was me trying to give a more understandable table than the one I actually have).
Where I'd got to was:
SELECT RowNo
FROM (SELECT ROW_NUMBER() OVER (ORDER BY DriverID) AS RowNo,Id
FROM DriverID_Table
WHERE Fleet IN (SELECT Fleet_ID FROM Fleet_Table WHERE User_Id=#user)) AS t
WHERE Id=#ID
using the value returned from that to calculate a page number and then a second query to fetch that page,
page = (int)RowNo/12; Offset = page*12;
SELECT *
FROM DriverID_Table
WHERE Fleet IN (SELECT Fleet_ID FROM Fleet_Table WHERE User_Id=#user)
ORDER BY DriverId
OFFSET #Offset ROWS FETCH NEXT 12 ROWS ONLY

Process SQL Table with no Unique Column

We have a table which keeps the log of internet usage inside our company. this table is filled by a software bought by us and we cannot make any changes to its table. This table does not have a unique key or index (to make the data writing faster as its developers say)
I need to read the data in this table to create real time reports of internet usage by our users.
currently I'm reading data from this table in chunks of 1000 records. My problem is keeping the last record I have read from the table, so I can read the next 1000 records.
what is the best possible solution to this problem?
by the way, earlier records may get deleted by the software as needed if the database file size gets big.
Depending on your version of SQL Server, you can use row_number(). Once the row_number() is assigned, then you can page through the records:
select *
from
(
select *,
row_number() over(order by id) rn
from yourtable
) src
where rn between 1 and 1000
Then when you want to get the next set of records, you could change the values in the WHERE clause to:
where rn between 1001 and 2000
Based on your comment that the data gets deleted, I would do the following.
First, insert the data into a temptable:
select *, row_number() over(order by id) rn
into #temp
from yourtable
Then you can select the data by row number in any block as needed.
select *
from #temp
where rn between 1 and 1000
This would also help;
declare #numRecords int = 1000 --Number of records needed per request
declare #requestCount int = 0 --Request number starting from 0 and increase 1 by 1
select top (#numRecords) *
from
(
select *, row_number() over(order by id) rn
from yourtable
) T
where rn > #requestCount*#numRecords
EDIT: As per comments
CREATE PROCEDURE [dbo].[select_myrecords]
--Number of records needed per request
declare #NumRecords int --(= 1000 )
--Datetime of the LAST RECORD of previous result-set or null for first request
declare #LastDateTime datetime = null
AS
BEGIN
select top (#NumRecords) *
from yourtable
where LOGTime < isnull(#LastDateTime,getdate())
order by LOGTime desc
END
Without any index you cannot efficiently select the "last" records. The solution will not scale. You cannot use "real-time" and "repeated table scans of a big logging table" in the same sentence.
Actually, without any unique identification attribute for each row you cannot even determine what's new (proof: say, you had a table full of thousands of booleans. How would you determine which ones are new? They cannot be told apart! You cannot find out.). There must be something you can use, like a combination of DateTime, IP or so. Or, you can add an IDENTITY column which is likely to be transparent to the software you use.
Probably, the software you use will tolerate you creating an index on some ID or DateTime column as this is transparent to the software. It might create more load, so be sure to test it (my guess: you'll be fine).

pulling data from a sql table that stores price history

I have been trying to figure out how to pull data out of sql table that holds the history of price changes for items in inventory. Example of how the data is laid out is below:
Item No Date changed Price
1 11/20/2012 15
2 11/28/2012 25
1 12/1/2012 18
I am needing to pull the last entry for each item no so that i can find where prices have change by more than a certain percent. Once I get the information all worked out but i am not sure how to pull only the last two updates for each item. Any help will be greatly appreciated
Simple order it by date and retrieve exactly two rows per id.
SELECT Price FROM table WHERE id=2 ORDER BY date_changed DESC LIMIT 0,2
This are the two last price changes.
This is how i got it to work.
create table ##inventoryitems (ID INT Identity(1,1),itemno char(11));
insert into ##inventoryitems
select distinct itemno
from InventoryActPkgCostHist
where LocID=3
create table ##temptable (item# char(11),changedate datetime,price numeric(8,2));
DECLARE #Counter INT
SET #Counter = 1
while #Counter<=(select COUNT(*) from ##inventoryitems)
begin
insert into ##temptable
select top 2 i.itemno,i.ActPkgCostDate,i.ActPkgCost
from InventoryActPkgCostHist i join ##inventoryitesm temp on i.itemno= temp.itemno
where temp.id=#Counter and locidd=3
order by itemno,ActPkgCostDate desc
set #Counter=#Counter+1
end
Thank you for everyone's help

Use SUM in update statement where criteria

I have been trying to search for this and am not sure I am using the correct terms. Or it might just be that it's not possible. But what I am trying to do is update all records in a table that make up a sum value that is less than a set value.
So here is an example:
ID type amount received_date processed_date
1 debit 10 7/1/2010 NULL
2 debit 10 7/2/2010 NULL
3 debit 10 7/3/2010 NULL
Now what I want to do is update all records that are equal to a sum of less than 22. So when I would do the sum id 1 and 2 would equal 20 which is less than 22. But it also needs to be only records that have a null for processed_date. I also want it to work so that it updates from oldest to newest.
Basically here is how I would write it in pseudo code:
UPDATE credits
SET date_processed = '8/1/2010'
WHERE SUM(amount) <= #total AND
credit_type = [debits]
But I know that this doesn't work. So I'm hoping some SQL master might have ideas.
I'm sure I could write this within a cursor but I'm wondering if there is a set based way to perform this.
EDIT: I updated the table and brief description below to better portray my circumstance.
Rows in a SQL table, represent an unordered list of items. Thus, we have to provide an order. In your example, you hint that it should process the rows ordered by Id.
Update TableName
Set processed_date = '2010-08-01'
Where [type] = 'debit'
And Exists (
Select 1
From TableName As C1
Where C1.Id <= TableName.Id
And C1.[type] = 'debit'
Having Sum(C1.amount) <= #total
)
As I mentioned in comments, it is not safe to depend on Id being the marker for sequence. It is possible to have gaps and for someone to insert "later" rows into those gaps using IDENTITY_INSERT. Instead, you should use a datetime column. If that column is received_date, then simply substitute Id for received_date in the above query.
You should use the HAVING clause for this type of situations.
According to w3schools, "The HAVING clause was added to SQL because the WHERE keyword could not be used with aggregate functions."
UPDATE credits
SET date_processed = '8/1/2010'
WHERE credit_type = [debits]
HAVING SUM(amount) <= #total
Here is a great tutorial found on w3schools
http://www.w3schools.com/SQL/sql_having.asp