Select only half the records - tsql

I am trying to figure out how to select half the records where an ID is null. I want half because I am going to use that result set to update another ID field. Then I am going to update the rest with another value for that ID field.
So essentially I want to update half the records someFieldID with one number and the rest with another number splitting the update basically between two values for someFieldID the field I want to update.

In oracle you can use the ROWNUM psuedocolumn. I believe in sql server you can use TOP.
Example:
select TOP 50 PERCENT * from table

You can select by percent:
SELECT TOP 50 PERCENT *fields* FROM YourTable WHERE ...

update x set id=#value from (select top 50 percent * from table where id is null) x

The following SQL will return the col_ids of the first half of the table.
SELECT col_id FROM table
WHERE rownum <= (SELECT count(col_id)/2 FROM table);
If the total number of col_ids is an odd number then you will get the first half - 1. This is because, for instance, we have 51 total records, the count(col_id)/2 returns 25.5, and since there is no rownum equal to this result, we get everything equal to 25 and below. That means the other 26 are not returned.
However, I have not seen the reverse statement working:
SELECT col_id FROM table
WHERE rownum > (SELECT count(col_id)/2 FROM table);
So if you want the other half of the table, you could just store the first results into a temp table, lets call it TABLE_A. Then just do MINUS on the original table from this table:
SELECT col_id FROM table
MINUS
SELECT col_id FROM table_a
Hopefully this helps someone.

Related

postgresql: how to get the last record even with WHERE clause

I have the following postgresql command
SELECT *
FROM (
SELECT *
FROM tablename
ORDER by id DESC
LIMIT 1000
) as t
WHERE t.col1="someval"
Now i also want to get the last record of along with the above query
FROM (
SELECT *
FROM tablename
ORDER by id DESC
LIMIT 1000
)
Currently i am doing
SELECT *
FROM (
SELECT *
FROM tablename
ORDER by id DESC
LIMIT 1000
) as t
WHERE t.col1="someval"
UNION ALL
SELECT *
FROM (
SELECT *
FROM tablename
ORDER by id DESC
LIMIT 1000
) as t
ORDER BY id ASC
LIMIT 1
Is this is the right way
I would use UNION rather than UNION ALL in this case, since the final row could also be returned by the first query, and I wouldn't want to have it twice in the result set if that happens. The primary key will guarantee that UNION can accidentally remove duplicate result rows.
I don't understand the query, in particular why there is a WHERE condition at the outside query in the first case, but not in the second. But that is unrelated to the question.
Your current effort is wrong, since the LIMIT 1 applies outside the UNION ALL, so you get only one row as a result. That this is wrong should have been immediately obvious upon testing, so it is baffling that you are asking us if it is right.
You should wrap the whole second SELECT in parenthesis, so the LIMIT applies just to it.
Better yet, rather than ordering and taking 1000 rows and then reversing the order and taking the first row, you could just do OFFSET 999 LIMIT 1 to get the 1000th row.
If the 1000th rows matches both conditions, do you want to see it twice?

PostgreSQL update certain row

I want to update verified from 'f' to 't' for certain rows, but it will update all the rows when I do this:
UPDATE
news
SET
verified = 't'
FROM
(
SELECT
verified
, ROW_NUMBER() OVER () AS rownum
FROM
news
) AS foo
WHERE
rownum = 1 or rownum = 15 or rownum = 32 or rownum = 54;
Can someone tell me where the problem is? Thanks
From the PostgreSQL documentation for the UPDATE clause:
When a FROM clause is present, what essentially happens is that the target table is joined to the tables mentioned in the from_list, and each output row of the join represents an update operation for the target table.
So, your query creates the cross product of the news table with the results of the SELECT clause, which of course is also the news table (which I will call "foo" because of your AS clause). Every single row from the news table is accompanied by every single row from the foo result table, creating nxn rows where n is the number of rows in news. So, for every news row, there is at least one foo row that is selected by the WHERE clause. Thus, every row of the news table is modified.
It's not clear to me what you are trying to do. (Can the OVER parameter be blank? And why select verified in the foo query?) But you may want to join each foo row to the proper news row in the WHERE clause, perhaps by primary key.

how to get rowNum like column in sqlite IPHONE

I have an Sqlite database table like this (with out ascending)
But i need to retrive the table in Ascending order by name, when i set it ascending order the rowId changes as follows in jumbled order
But i need to retrieve some limited number of contacts 5 in ascending order every time
like Aaa - Eeee and then Ffff- Jjjjj ......
but to se**t limits like 0-5 5-10 .... ** it can able using rowids since they are in jumble order
So i need another column like (rowNum in oracle) wich is in order 1234567... every time as follows
how to retrive that column with existing columns
Note: WE DONTE HAVE ROWNUM LIKE COLUMN IN SQLITE
The fake rownum solution is clever, but I am afraid it doesn't scale well (for complex query you have to join and count on each row the number of row before current row).
I would consider using create table tmp as select /*your query*/.
because in the case of a create as select operation the rowid created when inserting
the rows is exactly what would be the rownum (a counter). It is specified by the SQLite doc.
Once the initial query has been inserted, you only need to query the tmp table:
select rowid, /* your columns */ from tmp
order by rowid
You can use offset/limit.
Get the first, 2nd, and 3rd groups of five rows:
select rowid, name from contactinfo order by name limit 0, 5
select rowid, name from contactinfo order by name limit 5, 5
select rowid, name from contactinfo order by name limit 10, 5
Warning, using the above syntax requires SQLite to read through all prior records in sorted order. So to get the 10th record for statement number 3 above SQLite needs to read the first 9 records. If you have a large number of records this can be problematic from a performance standpoint.
More info on limit/ offset:
Sqlite Query Optimization (using Limit and Offset)
Sqlite LIMIT / OFFSET query
This is a way of faking a RowNum, hope it helps:
SELECT
(SELECT COUNT(*)
FROM Names AS t2
WHERE t2.name < t1.name
) + (
SELECT COUNT(*)
FROM Names AS t3
WHERE t3.name = t1.name AND t3.id < t1.id
) AS rowNum,
id,
name
FROM Names t1
ORDER BY t1.name ASC
SQL Fiddle example

To delete records beyond 20 from a table

At any time, I want my table to display the latest 20 rows and delete the rest.
I tried rownum > 20 but it said " 0 rows deleted" even when my table had 50 records.However, on triying rownum<20 - the first 19 records were deleted.
Please help.
ROWNUM is a pseudo-column which is assigned 1 for the first row produced by the query, 2 for the next, and so on. If you say "WHERE ROWNUM > 20", no row will be matched - the first row, if there was one, would have ROWNUM=1, but your predicate causes it to reject it - therefore the query returns no rows.
If you want to query just the latest 20 rows, you'd need some way of determining what order they were inserted into the table. For example, if each row gets a timestamp when it is inserted, this would usually be pretty reliable (unless you get thousands of rows inserted every second).
For example, a table with definition MYTABLE(ts TIMESTAMP, mycol NUMBER), you could query the latest 20 rows with a query like this:
SELECT * FROM (
SELECT ts, mycol FROM MYTABLE ORDER BY ts DESC
)
WHERE ROWNUM <= 20;
Note that if there is more than one row with exact same timestamp, this query may pick some rows non-deterministically if there are two or more rows tied for the 20th spot.
If you have an index on ts it is likely to use the index to avoid a sort, and Oracle will use stopkey optimisation to halt the query once it's found the 20th row.
If you want to delete the older rows, you could do something like this, assuming mycol is unique:
DELETE MYTABLE
WHERE mycol NOT IN (
SELECT mycol FROM (
SELECT ts, mycol FROM MYTABLE ORDER BY ts DESC
)
WHERE ROWNUM <= 20
);
The performance of this delete, if the number of rows to be deleted is large, will probably be helped by an index on mycol.

T-SQL: How to retrieve a 1/2 of total row count (basing on some criteria) or 50 first rows?

I wondering about how in T-SQL can I retrieve - let's say - 1/2 of total row count form a table (basing on some criteria) or even the first 50 rows (basing on some criteria too) ?
To select the top 50 rows:
SELECT TOP 50 *
FROM table1
WHERE ...
ORDER BY ...
To select the first half of the result set use PERCENT:
SELECT TOP 50 PERCENT *
FROM table1
WHERE ...
ORDER BY ...
Remember to add an ORDER BY if you want the results to be consistent.
First:
SELECT TOP 50 PERCENT a, b, c FROM table
Second:
SELECT TOP 50 a, b, c FROM table
As a rule, it's not advisable to do this unless you are also providing an ORDER BY (and in those times where it will work perfectly well to leave out the ORDER BY, your code will be more understandable and more robust to changes in the details of the underlying tables if you put it in).
Paging (e.g. returning the x block of y rows) is more cumbersome in SQLServer than many other SQL-language relational databases (more cumbersome than just about all of them to be honest), but can be done with ROW_NUMBER:
WITH OrderedTable AS
(
SELECT a, b, c, ROW_NUMBER() OVER (ORDER BY d) as rowNumber
FROM table
)
SELECT a, b, c FROM OrderedTable
WHERE rowNumber between 31 and 40
Will select the third set of ten rows, ordered by column d.
This latter method is also needed when the limit comes from a variable, as TOP does not allow something like TOP #number.
using SQL TOP Clause
SQL Server Syntax
SELECT TOP number|percent column_name(s)
FROM table_name
example :
SELECT TOP 50 PERCENT * FROM tablename
MySQL Syntax
SELECT column_name(s)
FROM table_name
LIMIT number
Oracle Syntax
SELECT column_name(s)
FROM table_name
WHERE ROWNUM <= number
Following works in MS SQL 2005 and 2008
select top 50 PERCENT * from x