Paging in SQL Server problems - sql-server

I have searched for paging in SQL Server. I found most of the solution look like that
What is the best way to paginate results in SQL Server
But it don't meet my expectation.
Here is my situation:
I work on JasperReport, for that: to export the report I just need pass the any Select query into the template, it will auto generated out the report
EX : I have a select query like this:
Select * from table A
I don't know any column names in table A. So I can't use
Select ROW_NUMBER() Over (Order By columsName)
And I also don't want it order by any columns.
Anyone can help me do it?
PS: In Oracle , it have rownum very helpful in this case.
Select * from tableA where rownum > 100 and rownum <200
Paging with Oracle

You should use ROW_NUMBER with an ORDER BY - because without an ORDER BY there is no determinism in how rows are returned. You can run the same query three times and get the results back in three different orders. Especially if merry-go-round scans come into play.
So unless you want your report to have the possibility of showing the same rows to users on multiple pages, or some rows never on any page, you need to find a way to order the result set to make it deterministic.

From my opinion, you can use sql query to find out how many columns in a table, and then find out a proper one for ' order by ' to depend on.
The script of how to get out columns of an table refer to : How can I get column names from a table in SQL Server?

Check out this link
http://msdn.microsoft.com/en-us/library/ms186734.aspx
SQL Server has similar function ROW_NUMBER. Though it behaves a bit differently.
SQL Server provides no guarantee of row order unless you have have specified a column in order by clause. I would recommend that you give an order by clause that has unique values.

Thank for all your help. Because of order by are required when paging in MS SQL Server, so I used ResultSetMetaData to get the Columns name and do paging as well.

You can use the below query aswell.
declare #test table(
id int,
value1 varchar(100),
value2 int)
insert into #test values(1,'10/50',50)
insert into #test values(2,'10/60',60)
insert into #test values(3,'10/60',61)
insert into #test values(4,'10/60',10)
insert into #test values(5,'10/60',11)
insert into #test values(6,'10/60',09)
select *
from ( select row_number() over (order by (select 0)) as rownumber,* from #test )test
where test.rownumber<=5

Related

snowflake merge statement using golden gate json as source table

while executing target table in snowflake using json data as source table
merge into cust tgt using (
select parse_json(s.$1):application_num as application num
from prd_json s qualify
row_number() over(partition application
order_by application desc)=1) src
on tgt.application =src.application
when not matched and op_type='I' then
insert(application) values (src.application );
qualify commands ignores all the duplicate data present and gives only unique record but while putting joins its show only less records when compare to normal select statement.
for example :
select distinct application
from prd_json where op_type='I';
--15000 rows are there
while putting joins it shows there is not matching records in target . if it is not matched it should insert all 15000rows but 8500 rows only inserting even though it was not an duplicate record . is there any function available without using "qualify" shall we insert the record. if i ignore qualify am getting dml error duplication. pls guide me if anyone knows.
How about using SELECT DISTINCT?
You demo SQL does not compile. and you using the $1 means it's also hard to guess the names of your columns to know how the ROW_NUMBER is working.
So it's hard to nail down the problem.
But with the following SQL you can replace ROW_NUMBER with DISTINCT
CREATE TABLE cust(application INT);
CREATE OR REPLACE table prd_json as
SELECT parse_json(column1) as application, column2 as op_type
FROM VALUES
('{"application_num":1,"other":1}', 'I'),
('{"application_num":1,"other":2}', 'I'),
('{"application_num":2,"other":3}', 'I'),
('{"application_num":1,"other":1}', 'U')
;
MERGE INTO cust AS tgt
USING (
SELECT DISTINCT
parse_json(s.$1):application_num::int as application,
s.op_type
FROM prd_json AS s
) AS src
ON tgt.application = src.application
WHEN NOT MATCHED AND src.op_type = 'I' THEN
INSERT(application) VALUES (src.application );
number of rows inserted
2
SELECT * FROM cust;
APPLICATION
1
2
running the MERGE code a second time gives:
number of rows inserted
0
Now if truncate CUST and I swap to using this SQL for the inner part:
SELECT --DISTINCT
parse_json(s.$1):application_num::int as application,
s.op_type
FROM prd_json AS s
qualify row_number() over (partition by application order by application desc)=1
I get three rows inserted, because the partition by application, is effectively binding to the s.application not the output application, and there are 3 different "applications" because of the other values.
The reason I wrote my code this way is your
select distinct application
from prd_json where op_type='I';
implies there is something called application already, in the table.. and thus it runs the chance of being used in the ROW_NUMBER statement..
Anyways, there is a large possible problem is you also have "update data" I guess U in your transaction block, that you want to ORDER BY the sub-select so you never have a Inser,Update trying action in Update,Inser order. And assuming you want all update operations if there are many of them.. I will stop. But if you do not have Updates, the sub-select should have the op_type='I' to avoid the non-insert ops making it. Out, or possible worse again, in your ROW_NUMBER pattern replacing the Intserts. Which I suspect is the underlying cause of your problem.

sql server: cannot replicate same order when creating tables

When I run this code, it gives me different sorting results. When I manually do this in Excel, I always get the same results. Can anyone help? Thanks.
select * into tblVSOELookupSort1 from tblVSOELookup order by
[SKU],[ASP Local],[Sum of Qty]
alter table tblVSOELookupSort1 add RowID int identity(1,1) not null
select * into tblVSOELookupSort2 from tblVSOELookupSort1 order by
[Region Per L/U],[Currency]
drop table tblVSOELookupSort1
drop table tblVSOELookup
exec sp_rename tblVSOELookupSort2, tblVSOELookup
select * from tblVSOELookup
That's normal. SQL databases in general do not guarantee a particular row ordering of results unless you specify one. The order is dependent on the RDBMS implementation, query plan, and other things. If you want a particular row ordering in your query results, you must include an ORDER BY clause in your query. In this case, select * from tblVSOELookup order by ....

SQL: Row number is different when sorting on columns with null values

In my C# application I'm using the following query to search for a particular string:
;WITH selectRows AS (SELECT *, row = ROW_NUMBER() OVER (ORDER BY <column_name>) FROM <table_name>)
SELECT row FROM selectRows WHERE <column_name> LIKE '%<search_string>%' COLLATE <collate> ORDER BY row;
This particular query always worked fine for me, even when the colum_name for the OVER ORDER BY clause was a column that contained null values. Yesterday I tried to search on a somewhat bigger SQL table (+- 1 million records), it suprised me that I got different row_numbers returned without changing the query between the executions. This only seem to happen on bigger tables and when the column_name for the OVER ORDER BY clause contains any null values. When the column_name is pointed to a column WITHOUT null values the query returns the same result over and over again.
I also tried the following query, but this did not work as well:
;WITH selectRows AS (SELECT *, row = ROW_NUMBER() OVER (ORDER BY ISNULL(<column_name>, '')) FROM <table_name>)
SELECT row FROM selectRows WHERE <column_name> LIKE '%<search_string>%' COLLATE <collate> ORDER BY row;
Note: both queries were tested on SQL Server 2012 and SQL Server 2008. The searched table also had a Primary Key (clustered) index on a Identity column and a nonclustered index on the column_name that is used for the OVER ORDER BY clause.
Thanks in advance!
You have specified an ordering criterion that is not a total order. Example: You order on a column that is always zero. That way the CTE can output a different row order each time.
You are filtering after ordering. That means your filter runs on different rows each time. It might happen to have a lot of matching rows or not.
In general SQL queries are not 100% deterministic thanks to certain constructs. There are more than this one.
Fix: Specify a total order. Use anything to break ties such as ORDER BY X, ID. As a habit I always specify a total order.

Selecting count without Group By

I have following table in SQL Server 2005. One order can have multiple containers. A container can be either Plastic or wood (New types may come in future).
I need to list the following columns -
OrderID, ContainerType, ContainerCOUNT and ContainerID.
Since I need to list the ContainerID also, the following group by approach won’t work.
DECLARE #OrderCoarntainers TABLE (OrderID INT, ContainerID INT, ContainerType VARCHAR(10))
INSERT INTO #OrderCoarntainers VALUES (1,101,'Plastic')
INSERT INTO #OrderCoarntainers VALUES (1,102,'Wood')
INSERT INTO #OrderCoarntainers VALUES (1,103,'Wood')
INSERT INTO #OrderCoarntainers VALUES (2,104,'Plastic')
SELECT OrderID,ContainerType,COUNT(DISTINCT ContainerID) AS ContainerCOUNT
FROM #OrderCoarntainers
GROUP BY OrderID,ContainerType
What is the best way to achive this?
Note: Upgrading SQL Server version is not an option for me.
Expected Result
You should be able to use a windowed function
SELECT OrderID,
ContainerType,
COUNT(ContainerID) OVER (PARTITION BY OrderID, ContainerType) AS ContainerCOUNT,
ContainerID
FROM #OrderCoarntainers
I really don't know SQL Server dialect of SQL that well, but I can suggest something that is pretty basic and may work. It relies on a join, which is not optimal for performance but will get the job done if the table is not huge or performance is not critical. Really the problem here is the table design is pretty bad for the data you are managing, as this should not all be in one table. But anyway:
SELECT o1.OrderID, o1.ContainerType, count(o2.ContainerID) AS ContainerCOUNT, o1.ContainerID
FROM #OrderCoarntainers o1 JOIN #OrderCoarntainers o2
ON o1.OrderID = o2.orderID AND o1.ContainerType = o2.ContainerType
GROUP BY o1.OrderID

Count of Distinct Rows Without Using Subquery

Say I have Table1 which has duplicate rows (forget the fact that it has no primary key...) Is it possible to rewrite the following without using a JOIN, subquery or CTE and also without having to spell out the columns in something like a GROUP BY?
SELECT COUNT(*)
FROM (
SELECT DISTINCT * FROM Table1
) T1
You can do something like this.
SELECT Count(DISTINCT ProductName) FROM Products
but if you want a count of completely distinct records then you will have to use one of the other options you mentioned.
If you wanted to do something like you suggested in the question, then that would imply you have duplicate records in your table.
If you didn't have duplicate records SELECT DISTINCT * from table would be the same without the distinct.
No, it's not possible.
If you are limited by your framework/query tool/whatever, can't use a subquery, and can't spell out each column name in the GROUP BY, you are SOL.
If you are not limited by your framework/query tool/whatever, there's no reason not to use a subquery.
if you really really want to do that you can just "SELECT COUNT(*) FROM table1 GROUP BY all,columns,here" and take the size of the result set as your count.
But it would be dailywtf worthy code ;)
I just wanted to refine the answer by saying that you need to check that the datatype of the columns is comparable - otherwise you will get an error trying to make them DISTINCT:
e.g.
com.microsoft.sqlserver.jdbc.SQLServerException: The ntext data type cannot be selected as DISTINCT because it is not comparable.
This is true for large binary, xml columns and others depending on your RDBMS - rtm. The solution for SQLServer for example is to cast it from an ntext to an nvarchar(MAX) from SQLServer 2005 onwards.
If you stick to the PK columns then you should be OK (I haven't verified this myself but I'd have thought logically that PK columns would have to be comparable)

Resources