SQL Server : copy a table into another table in reverse order - sql

I have a table that newer data starts with id=1 and increasing the id, we get to the older data, now the problem is, as new data will be added every day, and I want to show the results from new to old, there will be a problem. I want to reverse the order of the table that even after new data are added I can display the data from newer to older one.
Has anyone any clue what should I do?

You could hard-code the arbitrary number where the switch-over happens. Say you have 1,000 rows in there right now (so #1 is the newest, but #1001 will be the newest when it's added):
SELECT (CASE WHEN id < 1000 THEN id * -1 ELSE id END) AS sort_order
ORDER BY sort_order DESC
Probably the better solution would be to add a timestamp column, as it's not nice to rely on auto-generated columns for real data.
Edit
To create a new table, use the above with an insert.
INSERT INTO [new_table] (col1,col2,col3, ...)
SELECT (col1, col2, col3, ...)
FROM [old_table]
ORDER BY (CASE WHEN id < 1000 THEN id * -1 ELSE id END) DESC

It would be better to add a datetime field to you table.
However, your ID is not usable as order field directly since until now ID=1 was newest but from now on every new record will get a higher ID than X. So you need to identify X which is the ID value of the oldest record until now. Then you can order by two cases:
belongs it to the low-id=new or to the high-id=new group?
Here's an example where X=10:
SELECT ID
FROM dbo.tbl
ORDER BY CASE WHEN ID <=10 THEN ID ELSE -ID END ASC
Here's the fiddle: http://sqlfiddle.com/#!6/95c9a/3/0
but i want to copy the content to a new table so that i won't need to
treat them differently
Then you can use the sql above to insert into the new table in that order. I would use a new ID column with IDENTITY(1,1):
INSERT INTO dbo.tblCopy
SELECT ID
FROM dbo.tbl
ORDER BY CASE WHEN ID <=10 THEN ID ELSE -ID END ASC
If you don't want to add another column and you want to reuse the old id, you can use ROW_NUMBER with above CASE:
INSERT INTO dbo.tblCopy
SELECT ID =
ROW_NUMBER()OVER(ORDER BY CASE WHEN ID <=10 THEN ID ELSE -ID END ASC)
FROM dbo.tbl
Demo: http://sqlfiddle.com/#!6/00213/1/0

Related

Forming a record of a table from separated values?

*sorry, I couldn't find a better title for the question
ـــــــــــــــــــ
I'm implementing an audit feature, currently using the Audit tables provided by EntityFramework-Plus,
There are two tables, one that tracks the modification type, and in which entity (every record represents an update by the user):
[AuditEntryID]
,[EntitySetName]
,[EntityTypeName]
,[State]
,[StateName]
,[CreatedBy]
,[CreatedDate]
, and in the other table the corresponding changes for each modification, the most important columns are the OldValue and the NewValue for a specific PropertyName:
[AuditEntryPropertyID]
,[AuditEntryID]
,[RelationName]
,[PropertyName]
,[OldValue]
,[NewValue]
So to select all edits done on a specific table and for a specific Id, I run this query:
SELECT * FROM dbo.[AuditEntryProperties]
WHERE AuditEntryID IN (
SELECT AuditEntryID
FROM dbo.[AuditEntryProperties]
WHERE NewValue = '8b5f8272-8663-451d-8bf8-45d7d5db1529' AND PropertyName = 'CountryId')
AND AuditEntryID IN (
SELECT AuditEntryID
FROM dbo.[AuditEntries]
WHERE EntitySetName = 'TbCountries' )
Since the PK is inserted each time whether it's edit or delete, in the above query I select all the history of the given Id.
What I need is that I want to implement feature that the user can go back to a specific record at specific time.
I drew this in paint, it depict the idea:
the first row is insert state , the second row there are edit on col1 and col2 , the third row is and edit on col1 and col3..etc.
the col1 is a primary key so its inserted every time (it's value doesn't change!)
Now the most recent record is the mod6, and I need to go back to the mod3, so I'll take the col1 value from mod3 and the col2 value from mod2, col3 from mod3, col4 from mod1.
my problem is how to form a full record of type TbCountries from the table [AuditEntryProperties] at a specific AuditEntryID?
You can get the list of properties and values using row_number():
select aep.*
from (select ae.EntitySetName, aep.propertyname, aep.newvalue,
row_number() over (partition by ae.EntitySetName, aep.propertyname
order by ae.createddate desc
) as seqnum
from dbo.AuditEntries ae join
dbo.AuditEntryProperties aep
on ae.AuditEntryID = aep.AuditEntryID
where ae.createddate < #date and ae.EntitySetName = #tbl
) aep
where seqnum = 1;
This gives the values as one-per-row. You can then pivot or use conditional aggregation if you want them on a single row.

How can i sort table records in SQL Server 2014 Management Studio by Alphabetical?

I have many record in one table :
1 dog
2 cat
3 lion
I want to recreate table or sort data with this Alphabetical order :
1 cat
2 dog
3 lion
Table 1
Id int Unchecked
name nvarchar(50) Checked
To create another table from your table :
CREATE TABLE T1
( ID INT IDENTITY PRIMARY KEY NOT NULL,
NAME NVARCHAR(50) NOT NULL
)
GO
INSERT INTO T1 VALUES ('Dog'),('Cat'),('Lion');
SELECT ROW_NUMBER ()OVER (ORDER BY NAME ASC) ID, NAME INTO T2 FROM T1 ORDER BY NAME ASC;
If you just want to sort the table data, use Order by
Select * from table_1 order by Name
If you want to change the Id's as well according to alphabetical order, create a new table and move the records to the new table by order.
SELECT RANK() OVER (ORDER BY name ) AS Id, name
INTO newTable
FROM table_1
In your database, the order of the records as they were inserted into the table does not necessarily dictate the order in which they're returned when queried. Nor does the ordering of a clustered key. There may be situations in which you appear to always get the same ordering of your results, but that is not guaranteed and may change at any time.
If the results of a query must be a specific order, then you must specify that ordering with an ORDER BY clause in your query (ORDER BY [Name] ASC in this particular case).
I understand, based upon your comments above, that you don't want this to be the answer. But this is how SQL Server (and any other relational database) works. If order matters, you specify that upon querying data from the system, not when inserting data into it.

how to create an order column in sql server

i want an order info for every row in my table. the following is my table. ID column is identity and its primary key. Order column is computed from id column.
ID -- Name -- Order
1 kiwi 1
2 banana 2
3 apple 3
everything is fine and i have an order column. But i cant switch the orders of rows.
for example i cant say that from now on kiwi's order becomes 2 and banana's order becomes 1
in other words if we would update a computed column then my problem could be solved.
if i dont create order column as computed column then for every new entry i have to compute largest order so that i can write (largest order) + 1 for new entry's order. But i do not calculate largest number for every entry since it is costly.
So what should i do now?
I ve searched and the solutions i found creating trigger function etc. i do not want to do that too.
I might not have understood the question - I don't think its very clear.
but why use a counter to order the set, couldnt you just use a timestamp for each order and use that to dictate which order is more recent?
CREATE TABLE dbo.Test (
ID INT IDENTITY(1,1),
Name varchar(50),
OrderTime Datetime
)
INSERT INTO dbo.TEST (Name,OrderTime)
VALUES ('kiwi',Getdate())
SELECT *
FROM dbo.TEST
ORDER BY OrderTime
if you needed an integer based on the order time you could use a rownumber function to return one;
SELECT *,
ROW_NUMBER() OVER (ORDER BY OrderTime Desc) as OrderInt
FROM dbo.TEST

ORACLE SQL - Need query to return one row (ID exists multiple times)

In need of some assistance... I've tried for awhile and can't get what I need. (it's going to be used as a sub query within the FROM statement of another query) that will return the creator ID and 1 note. I only need ONE row returned per ID. (Can be any of the notes that matches the creator ID -- doesn't matter) The creator ID is a key that shows up multiple times in the table.
Here is one way:
select t.*
from (select t.*, row_number() over (partition by creator order by ordnum) as seqnum
from notes t
) t
where seqnum = 1;

Getting the last record in SQL in WHERE condition

i have loanTable that contain two field loan_id and status
loan_id status
==============
1 0
2 9
1 6
5 3
4 5
1 4 <-- How do I select this??
4 6
In this Situation i need to show the last Status of loan_id 1 i.e is status 4. Can please help me in this query.
Since the 'last' row for ID 1 is neither the minimum nor the maximum, you are living in a state of mild confusion. Rows in a table have no order. So, you should be providing another column, possibly the date/time when each row is inserted, to provide the sequencing of the data. Another option could be a separate, automatically incremented column which records the sequence in which the rows are inserted. Then the query can be written.
If the extra column is called status_id, then you could write:
SELECT L1.*
FROM LoanTable AS L1
WHERE L1.Status_ID = (SELECT MAX(Status_ID)
FROM LoanTable AS L2
WHERE L2.Loan_ID = 1);
(The table aliases L1 and L2 could be omitted without confusing the DBMS or experienced SQL programmers.)
As it stands, there is no reliable way of knowing which is the last row, so your query is unanswerable.
Does your table happen to have a primary id or a timestamp? If not then what you want is not really possible.
If yes then:
SELECT TOP 1 status
FROM loanTable
WHERE loan_id = 1
ORDER BY primaryId DESC
-- or
-- ORDER BY yourTimestamp DESC
I assume that with "last status" you mean the record that was inserted most recently? AFAIK there is no way to make such a query unless you add timestamp into your table where you store the date and time when the record was added. RDBMS don't keep any internal order of the records.
But if last = last inserted, that's not possible for current schema, until a PK addition:
select top 1 status, loan_id
from loanTable
where loan_id = 1
order by id desc -- PK
Use a data reader. When it exits the while loop it will be on the last row. As the other posters stated unless you put a sort on the query, the row order could change. Even if there is a clustered index on the table it might not return the rows in that order (without a sort on the clustered index).
SqlDataReader rdr = SQLcmd.ExecuteReader();
while (rdr.Read())
{
}
string lastVal = rdr[0].ToString()
rdr.Close();
You could also use a ROW_NUMBER() but that requires a sort and you cannot use ROW_NUMBER() directly in the Where. But you can fool it by creating a derived table. The rdr solution above is faster.
In oracle database this is very simple.
select * from (select * from loanTable order by rownum desc) where rownum=1
Hi if this has not been solved yet.
To get the last record for any field from a table the easiest way would be to add an ID to each record say pID. Also say that in your table you would like to hhet the last record for each 'Name', run the simple query
SELECT Name, MAX(pID) as LastID
INTO [TableName]
FROM [YourTableName]
GROUP BY [Name]/[Any other field you would like your last records to appear by]
You should now have a table containing the Names in one column and the last available ID for that Name.
Now you can use a join to get the other details from your primary table, say this is some price or date then run the following:
SELECT a.*,b.Price/b.date/b.[Whatever other field you want]
FROM [TableName] a LEFT JOIN [YourTableName]
ON a.Name = b.Name and a.LastID = b.pID
This should then give you the last records for each Name, for the first record run the same queries as above just replace the Max by Min above.
This should be easy to follow and should run quicker as well
If you don't have any identifying columns you could use to get the insert order. You can always do it like this. But it's hacky, and not very pretty.
select
t.row1,
t.row2,
ROW_NUMBER() OVER (ORDER BY t.[count]) AS rownum from (
select
tab.row1,
tab.row2,
1 as [count]
from table tab) t
So basically you get the 'natural order' if you can call it that, and add some column with all the same data. This can be used to sort by the 'natural order', giving you an opportunity to place a row number column on the next query.
Personally, if the system you are using hasn't got a time stamp/identity column, and the current users are using the 'natural order', I would quickly add a column and use this query to create some sort of time stamp/incremental key. Rather than risking having some automation mechanism change the 'natural order', breaking the data needed.
I think this code may help you:
WITH cte_Loans
AS
(
SELECT LoanID
,[Status]
,ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS RN
FROM LoanTable
)
SELECT LoanID
,[Status]
FROM LoanTable L1
WHERE RN = ( SELECT max(RN)
FROM LoanTable L2
WHERE L2.LoanID = L1.LoanID)