Using subtraction of two queries in SELECT TOP query - sql

I am struggling to prepare a query like this in SQL Server:
I have a table where I have a specific, constant value, let's say it's 15 (column defined as float)
In the same table I have one column where sometimes there is a value and sometimes it is a NULL value
So I would like to use SELECT TOP () query that would show me the number of records that is a result of subtraction of two queries:
SELECT
(SELECT DISTINCT Records
FROM Brand.Alle
WHERE HdNummer = '33')
-
(SELECT COUNT(AbrufNr)
FROM Brand.Alle
WHERE HdNummer = '33'
AND Transaction IS NOT NULL) AS DIFFERENCE
This query returns the result I want to have (let's say 13).
I would like to have selected top 13 records from a table I run a query against:
SELECT TOP (SELECT
(SELECT DISTINCT Records FROM Brand.Alle
WHERE HdNummer = '33')
-
(SELECT COUNT(AbrufNr) FROM Brand.Alle
WHERE HdNummer = '33' AND Transaction IS NOT NULL) AS DIFFERENCE) *
FROM Brand.Alle
WHERE HdNummer = '33' AND Transaction IS NULL
ORDER BY NEWID()
but it fails due to an error saying that I need to use an integer in select top statement. So the question is: how can I convert the value I receive as a result of subtraction two queries so I could use in in SELECT TOP?
I would highly appreciate any help.
Thank you in advance.

Number all your rows and only keep those with a number less or equal to the desired count.
with numbered as
(
select
alle.*,
row_number() over (order by newid()) as rn
from brand.alle
where hdnummer = 33
)
select *
from numbered
where rn <= ( <your count query here> );
Your count query can probably written shorter along the lines of:
select
count(distinct records) -
count(case when transaction is not null then abrufnr end) as cnt
from brand.alle
where hdnummer = 33;
And you can even combine the two with window functions in order to read from the table only once.
with numbered_and_counted as
(
select
alle.*,
count(distinct records) over () -
count(case when transaction is not null then abrufnr end) over () as cnt,
row_number() over (order by newid()) as rn
from brand.alle
where hdnummer = 33
)
select *
from numbered_and_counted
where rn <= cnt;

Related

How to get max value and using group by clause

I have a query like this:
select transactions_id,
time_stamp,
clock
from times
group by transactions_id
having sum(distinct type) = 1
now, I would like to get max value depending on id.
I used below queries but not worked:
select max(id),
transactions_id,
time_stamp,
clock
from times
group by transactions_id
having sum(distinct type) = 1
or
select transactions_id,
time_stamp,
clock
from times
group by transactions_id
having sum(distinct type) = 1
and max(id)
for example:
I have three conditions:
type must be 1
group by transactions_id
max id
You can find aggregates in one query and join its result with the table to get the relevant rows.
select *
from times t1
join (
select transactions_id,
max(id) as id
from times
where type = 1
group by transactions_id
) t2 using (transactions_id, id);
If I understand correctly, you can use the ANSI standard row_number() function:
select t.*
from (select t.*,
row_number() over (partition by transactions_id order by id desc) as seqnum
from times t
) t
where seqnum = 1;
I am not sure what having sum(distinct type) = 1. That condition is not explained in the question.

DISTINCT with PagedResults

I am sure this will be answered somewhere...
Aim: Get DISTINCT DOCURL and additional columns
Tried:
1. Changing SELECT * FROM to SELECT DISTINCT DOCURL FROM which only yields the DOCURL column
2. Adding DISTINCT into the second select (as per example) but again I get all columns and rows.
Notes: Code is normally built dynamically so I've taken the print...
SELECT *
FROM
(
Select DISTINCT
isnull(d.DOCURL,'-') As DOCURL,
isnull(d.ID,'-') As ID,
isnull(d.UPRN,'-') As UPRN,
isnull(d.VFMDISCIPLINE,'-') As VFMDISCIPLINE,
isnull(d.VFMDISCIPLINEELEMENT,'-') As VFMDISCIPLINEELEMENT ,
isnull(d.SurveyDate,' ') As SurveyDate,
isnull(d.WorkOrder,'-') As WorkOrder,
ROW_NUMBER() OVER (ORDER BY DOCURL) AS ResultSetRowNumber
From TblData As D
WHERE 1 = 1
AND d.UPRN = '123XYZ'
AND (d.VFMDISCIPLINE = '1' OR d.VFMDISCIPLINE = '2' )
) As PagedResults
WHERE ResultSetRowNumber > 0 And ResultSetRowNumber <= 20
Assuming DOCURL is a unique column, the issue with the DISTINCT statement is that a new row number will be generated for each row in the sub query, therefore all rows will be considered different. You should apply distinct first and then get the row numbers.
Edit: I removed DISTINCT since your result set do not satisfy the criteria. Instead, I've added a partition inside the sub query, this way row numbers will start from 1 for each unique DOCURL and they're ordered by ID since I just assumed that's what you mean by first. Outer query reassigns row_numbers based on unique results from the sub query.
Select * From (
SELECT *, ROW_NUMBER() OVER (ORDER BY DOCURL) AS ResultSetRowNumber
FROM
(
Select
isnull(d.DOCURL,'-') As DOCURL,
isnull(d.ID,'-') As ID,
isnull(d.UPRN,'-') As UPRN,
isnull(d.VFMDISCIPLINE,'-') As VFMDISCIPLINE,
isnull(d.VFMDISCIPLINEELEMENT,'-') As VFMDISCIPLINEELEMENT ,
isnull(d.SurveyDate,' ') As SurveyDate,
isnull(d.WorkOrder,'-') As WorkOrder,
ROW_NUMBER() OVER (PARTITION BY d.DOCURL ORDER BY d.ID) As PART
From TblData As D
WHERE 1 = 1
AND d.UPRN = '123XYZ'
AND (d.VFMDISCIPLINE = '1' OR d.VFMDISCIPLINE = '2' )
) As t Where PART = 1
) As PagedResults
WHERE ResultSetRowNumber > 0 And ResultSetRowNumber <= 20

Oracle SQL Query taking longer with OR statement

I have a query that takes no time at all:
select count(*) from mytable where processed_status = 0 and tid not in
(select max(tid) from mytable group by userid)
tid is an auto-incremented unique identifier. I'm grabbing all the rows from mytable that are not the latest row based on userid. These are duplicate rows and I'm discarding them. Now I'm adding another filter to grab a specific row as well as all of the rows from the above query. I run the following query and it runs for 10 min before I kill it.
select count(*) from mytable where processed_status = 0 and (tid = 5 or tid not in
(select max(tid) from mytable group by userid))
if there is a better way to grab all the duplicate rows, I would be interested in some ideas as well.
You can use the ROW_NUMBER() analytic function:
SELECT COUNT(*)
FROM (
SELECT tid,
ROW_NUMBER() OVER ( PARTITION BY userid ORDER BY tid DESC ) AS rn
FROM mytable
WHERE processed_status = 0
)
WHERE tid = 5
OR rn > 1

Total Row Count in sql query---sql server 2008

My query is as follows
BEGIN
WITH MyCTE
AS (
SELECT T.MusicAlbumTitle
,D.musicTitle
,D.mVideoID
,D.musicFileName
,T.ReleaseDate AS ReleasedDate
,D.MusicLength
,D.musicSinger
,D.MusicVideoID
,D.ExternalLink
,D.CoverImg
,ROW_NUMBER() OVER (
PARTITION BY D.MusicVideoID ORDER BY D.mVideoID
) AS row_num
FROM dbo.Music_Video T
JOIN dbo.Music_Video_Details D ON T.MusicVideoID = D.MusicVideoID
WHERE T.PortalID = #PortalID
AND T.CultureCode = #CultureCode
AND T.ComingSoon <> 1
GROUP BY T.MusicAlbumTitle
,D.musicTitle
,D.mVideoID
,T.ReleaseDate
,D.musicFileName
,D.MusicLength
,D.musicSinger
,D.MusicVideoID
,D.ExternalLink
,D.CoverImg
)
SELECT a.mVideoID
,a.MusicVideoID
,a.musicFileName
,a.MusicAlbumTitle
,a.ReleasedDate
,a.row_num
,a.CoverImg
,a.ExternalLink
,a.musicTitle
,a.MusicLength
FROM MyCTE a
WHERE row_num = 1
ORDER BY MusicVideoID DESC
END
I need to achieve total row count from last select statement.
which mean total row count that is being selected.
or any idea that might be use in this condition
How can i do this ..
Please add COUNT(*) OVER() in your select, which returns total rows selected as a new column.
Ex:
SELECT
*,
COUNT(*) OVER() AS [Total_Rows]
FROM YourTable
Just to be clear, you need to add the count to the CTE, not the outer query. The outer select is returning only one row, so the count would always be one.
The CTE should start:
WITH MyCTE
AS (
SELECT T.MusicAlbumTitle
,D.musicTitle
,D.mVideoID
,D.musicFileName
,T.ReleaseDate AS ReleasedDate
,D.MusicLength
,D.musicSinger
,D.MusicVideoID
,D.ExternalLink
,D.CoverImg
,ROW_NUMBER() OVER (
PARTITION BY D.MusicVideoID ORDER BY D.mVideoID
) AS row_num,
COUNT(*) over () as total_count

SQL: If no rows found, do another search?

I need to write a query which would always return something, even if nothing satisfies conditions, something like this
SELECT * WHERE date > NOW() FROM table ORDER by date
IF none is returned THEN
SELECT FIRST FROM table ORDER by date
So only numbers more then 10 will be returned, if none is returned, return any number
Any ideas how to do it?
Here is one way, using union all:
select *
from table
where number > 10
union all
(select *
where number > 0 and
not exists (select * from table where number > 10)
limit 1
)
If you are using a reasonable version of SQL, you could do something like:
select t.*
from (select t.*, max(number) over () as maxnumber,
row_number() over (order by number desc) as seqnum
from table t
) t
where (maxnumber > 10 and number > 10) or seqnum = 1
You need window functions for this.