Can I use TOP and Count in a single SELECT of SQL? - sql

I am using SQL Server2008R2. I have below SQL select statement:
select column1, max(column2), min(column3)
from myTable
group by column1
order by column1
Let's say the above select statement returns 1001 records.
Let it return TOP 5 is not hard:
select top 5 column1, max(column2), min(column3)
from myTable
group by column1
order by column1
How can I modify the above statement so 1001 will also return and hence I know how many records in total?
I want some result like this:
1001 column1 max(column2) min(column3) -- top#1 row data
1001 column2 max(column2) min(column3) -- top#2 row data
1001 column1 max(column2) min(column3) -- top#3 row data
1001 column2 max(column2) min(column3) -- top#4 row data
1001 column2 max(column2) min(column3) -- top#5 row data
1001 is the total number of available records, and I only select top 5 of them. I want to know the total number and the details for top 5.

One method is with a subquery:
select top 5 *
from (select count(*) over () as cnt, column1, max(column2), min(column3)
from myTable
group by column1
) t
order by column1;
Although I prefer the subquery to prevent ambiguity, it also works without the subquery:
select top 5 count(*) over () as cnt, column1, max(column2), min(column3)
from myTable
group by column1
order by column1;

You can use the count() over() window function..
select top 5
count(*) over (),
column1,
max(column2),
min(column3)
from myTable
group by column1
order by column1

Related

Select row after filter row has a coincident column in sql

I have a database as below
Column1 column2 column3
A123 abc Def
A123 xyz Abc
B456 Gh Ui
I want to select rows which don't have coincident content in column 1 by sql command.
In this case, The expected result is only row 3rd.
How to do it?
Thanks
you could use a join with a subselect for count =1
select * from my_table m
inner join (
select column1, count(*)
from my_table
group by column_1
having count(*) =1
) t on t.column_1 = m.column_1
WITH CTE AS (Select COUNT(Column1) OVER(PARTITION BY Column1 ) as coincident,* from table )Select * from CTE where coincident =1
I would use window functions:
select Column1, column2, column3
from (select t.*, count(*) over (partition by column1) as cnt
from t
) t
where cnt = 1;
However, there are other fun ways. For instance, aggregation:
select column1, max(column2) as column2, max(column3) as column3
from t
group by column1
having count(*) = 1;
Or if you know one of the other columns is going to have different values on different rows, then not exists may be the most efficient solution:
select t.*
from t
where not exists (select 1
from t t2
where t2.column1 = t.column1 and
t2.column2 <> t.column2
);

Subtract 2 rows using case statement in SQL Server 2008

My data is like below, it's in a single table
Column1 Column2
abc 100
abc 200
Now I need like below
abc 100 //here 200-100
I am banging my head on how to achieve this.
I have tried to use the row_number and then subtract using case statement like
Select
column1,
sum(
case when rownum=1
then column2
end
-
case when rownum=2
then column2
end
)
from table
group by column1
But this is giving me null.
Assuming there is no attribute which can define row ordering -
;with cte as(
select
row_number() over (order by (select null)) as IndexId,
Column1,
Column2
from #xyz
)
select sum(case when IndexID=1 then (-1 * Column2) else Column2 end), Column1
from cte
group by Column1
Input data-
declare #xyz table(Column1 varchar(10),Column2 int)
insert into #xyz
select 'abc' ,100 union all
select 'abc' ,200
Assuming you have an attribute rownum in table which is always 1 or 2 (it can be generated by some row_number() as you suggest in question, according to any order that is suitable for you)
Column1 Column2 Rownum
------------------------
abc 100 1
abc 200 2
then you can simply use
Select
column1,
sum(
case when rownum=1
then column2
else -column2
end
)
from table
group by column1
It performs a sum of the Column2 per Column1, however, in the row having rownum = 2 the Column2 value is negated. Therefore in our example you end up with 100 + (-200) = -100
You could do:
select column1, max(column2) - min(column2)
from t
group by column1;
Here is a short form of the answer above if you care:
SELECT
column1,
SUM(IIF(rownum=1,column2,-column2))
FROM table
GROUP BY column1

Oracle sql, select First Row while selecting other things

What do I need to add to the query below to get just the first row that shows up after this query?
Query:
SELECT column1,
column2,
MIN (column3),
MIN (colmun4)
FROM table
WHERE column0 = 'value'
GROUP BY column1, column2
Current Results:
column1 column2 column3 column4
30187 C 201330 1/3/2013 2:49:35 PM //I want this row only
33459 C 201330 1/3/2013 4:32:42 PM
90855 C 201390 3/28/2013 9:20:44 AM
96077 RA 201390 7/1/2013 11:31:46 AM
select * from (
SELECT column1,
column2,
MIN (column3),
MIN (colmun4)
FROM table
WHERE column0 = 'value'
GROUP BY column1, column2)
where rownum = 1
or if you're using oracle 12c you can use the below,
SELECT column1,
column2,
MIN (column3),
MIN (colmun4)
FROM table
WHERE column0 = 'value'
GROUP BY column1, column2
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY;

Duplicates 101 from basic search to delete?

Goal is to find duplicates.
Select Column1, Column2, Column3
from Tablename
where Column1 = 1111 and Column2 = 2222
group by Column1, Column2, Column3
having count(*) > 1
This select query finds all the rows that are duplicates. I want to delete them all so I changed select to delete:
Delete from Tablename
where Column1 = 1111 and Column2 = 2222
group by Column1, Column2, Column3
having count(*) > 1
I get an error that says I can't use "group by".
What is another option to delete them all?
Try this query:
with v1 as
(select
ROW_NUMBER() OVER (ORDER BY Column1) AS ID,t1.*
FROM Tablename t1)
DELETE FROM v1 where Column1=1111 and Column2=2222
and id not in (select min(id) from v1 group by
Column1, Column2, Column3);
SQL Fiddle

Sampling unique set of records in Oracle table

I have an Oracle table that from which I need to select a given percentage of records for each type of a given set of unique column combination.
For example,
SELECT distinct column1, column2, Column3 from TableX;
provides me all the combination of unique records from that table. I need a % of each rows from each such combination. Currently I am using the following query to accomplish this, which is lengthy and slow.
SELECT *
FROM tableX Sample ( 3 )
WHERE Column1 = ‘value1’ and
Column2 = ‘value2’ and
Column3 = ‘value3
UNION
SELECT *
FROM tableX Sample ( 3 )
WHERE Column1 = ‘value1’ and
Column2 = ‘value2’ and
Column3 = ‘value4
UNION
…
…
SELECT *
FROM tableX Sample ( 3 )
WHERE Column1 = ‘valueP’ and
Column2 = ‘valueQ’ and
Column3 = ‘valueR’
Where the combination of suffix in the “Value” is unique for that table (obtained from the first query)
How can I improve the length of the query and speed?
Here is one approach:
select t.*
from (select t.*,
row_number() over (partition by column1, column2, column3 order by dbms_random()
) as seqnum,
count(*) over (partition by column1, column2, column3) as totcnt
from tablex t
) t
where seqnum / totcnt <= 0.10 -- or whatever your threshold is
It uses row_number() to assign a sequential number to rows in each group, in a random order. The where clause chooses the proportion that you want.