rank() equivalent for SQL Server 2000 - sql-server

I am using SQL Server 2000 so sadly common table expressions are out but I have the following 2 table structure:
Invoices
id
InvoiceQueryReasons
id
invoice_id
reason
date_queried
I want to inner join from Invoices to InvoiceQueryReasons and only get 1 row for each invoice that selects the most recent InvoiceQueryReasons record.
If I was using a CTE with postgress I would do something like:
SELECT *
FROM
(SELECT
"i"."id", "iq"."reason", "iq"."date_queried",
rank() OVER (PARTITION BY "invoice_id" ORDER BY "date_queried" DESC) AS "invoice_query_rnk",
FROM "invoices" i
INNER JOIN "InvoiceQueryReasons" iq ON ("i"."id" = "iq"."invoice_id")
) AS "iqrs"
INNER JOIN
"invoices" ON ("iqrs"."id" = "invoices"."id")
WHERE
("invoice_query_rnk" = 1)
Apologies if the query is not exactly right, I am writing this on a non-dev machine.
How could I write a similar query in SQL Server 2000 where I do not have common table expression?

This is the way I always used to do this in SQL Server 2000:
FROM Table1
INNER JOIN Table2 ON Table2.PrimaryKey=(
SELECT TOP 1 t2.PrimaryKey
FROM Table2 t2
WHERE t2.ForeignKey=Table1.PrimaryKey
ORDER BY t2 DateColumn DESC
)

Related

Selecting count of exist rows in other table and join it to our SQL server table

I have two tables in SQL server. first one is table of customers info and second includes all purchases,
At first Table i have id of our customers, and the purchases table although has the id of who bought that product. so how can i select all customers table that include how many time they purchased products?
i tried this
SELECT TOP 2000 COUNT(tblpurchase.id) as id2,tblcustomers.* From tblpurchase
right join on tblpurchase.id=tblcustomers.id
but didn't word. how can i solve this?
Use OUTER APPLY
SELECT TOP 2000 tblcustomers.* ,M.CustomerCount
From tblcustomers
OUTER APPLY(
SELECT COUNT(*) as CustomerCount
from tblpurchase
WHERE tblpurchase.CustomerIDColumn = tblcustomers.id
)M
Here tblpurchase.CustomerIDColumn use actual name of customerID column
Also you can with LEFT JOIN
SELECT TOP 2000
C.*,
P.CustomerCount
From
tblcustomers C LEFT JOIN
(
SELECT
TP.CustomerId,
COUNT(*) as CustomerCount
FROM
tblpurchase TP
GROUP BY
TP.CustomerId
) P ON C.Id = P.CustomerId

How to do count(*) for specific alias in SQL server?

I have an SQL command with multiple tables added with LEFT JOIN table1 AS alias. I want to count all rows in table1, but not table2.
In a command where there's only one table, I can just do count(*). Here, however, * refers to all the rows in all the conjoined tables. table1.* gets all the rows from just that table, but count(table1.*) throws an Incorrect syntax near '*'. error.
Is this a syntax problem, or something deeper? How do I get the desired functionality?
Running Microsoft SQL Azure (RTM) - 12.0.2000.8
Instead of query like this
select *,count(C.CustomerID) over (partition by U.UserID)
from Users U
left join Customers C on C.ManagerID = U.UserID
where U.UserID between 1574 and 1580
You can use query like this
select *
from Users U
outer apply (
select Cnt = count(*) from Customers
where ManagerID = U.UserID ) res
where U.UserID between 1574 and 1580

Convert T-SQL Cross Apply to Oracle

I'm looking to convert this SQL Server (T-SQL) query that uses a cross apply to Oracle 11g. Oracle does not support Cross Apply until 12g, so I have to find a work-around. The idea behind the query is for each Tab.Name that = 'Foobar', I need find the previous row's name with the same ID ordered by Tab.Date. (This table contains multiple rows for 1 ID with different Name and Date).
Here is the T-SQL code:
SELECT DISTINCT t1.ID
t1.Name,
t1.Date,
t2.Date as 'PreviousDate',
t2.Name as 'PreviousName'
FROM Tab t1
OUTER apply (SELECT TOP 1 t2.Date,
t2.Name
FROM Tab t2
WHERE t1.Id = t2.Id
ORDER BY t2.Date DESC) t2
WHERE t1.Name = 'Foobar' )
Technically, I was able to recreate this same functionality in Oracle using LEFT JOIN and LAG() function:
SELECT DISTINCT t1.ID
t1.Name,
t1.Date,
t2.PreviousDate as PreviousDate,
t2.PreviousName as PreviousName
FROM Tab t1
LEFT JOIN (
SELECT ID,
LAG(Name) OVER (PARTITION BY ID ORDER BY PreviousDate) as PreviousName,
LAG(Date) OVER (PARTITION BY ID ORDER BY PreviousDate) as PreviousDate
FROM Tab) t2 ON t2.ID = t1.ID
WHERE t1.Name = 'Foobar'
The issue is the order it executes the Oracle query. It will pull back ALL rows from Tab, order them (because of the LAG function), then it will filter them down using the ON statement when it joins it to the main query. That table has millions of records, so doing that for EACH ID is not feasible. Basically, I want to change the order of operations in the sub-query to just pull back rows for a single ID, sort those rows to find the previous, and join that. Any ideas on how to tweak it?
TL;DR
SQL Server: filters, orders, joins
Oracle: orders, filters, joins
You can look for the latest row per (id) group with row_number():
select *
from tab t1
left join
(
select row_number() over (
partition by id
order by Date desc) as rn
, *
from t2
) t2
on t1.id = t2.id
and t2.rn = 1 -- Latest row per id

Small ms Sql query to get the max of an id with some criteria

I want sql query to get the above result. The result is the maximum Id in TableA whose s_id in TableB has Stat=true i.e. 1.
The following does not do what I want:
select i.category_id,i.image_id,i.image_original,i.image_title,i.photographer
from images i
inner join schedule s
on i.scheduleid=s.scheduleid
and s.status='live'
where image_id=(select max(image_id) from images)
Use TOP to retrieve only 1 row
Use ORDER BY to control the sorting, so you get the single row you want
SELECT TOP(1) a.id, a.[image], a.s_id, b.stat, b.[desc]
FROM TableA a
JOIN TableB b on a.s_id = b.s_id
WHERE b.stat = 1
ORDER BY A.ID DESC
An SQLFiddle showing this.

How to create RowNum column in SQL Server?

In Oracle we have "rownum".
What can I do in SQL Server?
In SQL Server 2005 (and 2008) you can use the ROW_NUMBER function, coupled with the OVER clause to determine the order in which the rows should be counted.
Update
Hmm. I don't actually know what the Oracle version does. If it's giving you a unique number per row (across the entire table), then I'm not sure there's a way to do that in SQL Server. SQL Server's ROW_NUMBER() only works for the rows returned in the current query.
If you have an id column, you can do this:
select a.*,
(select count(*) from mytable b where b.id <= a.id) as rownum
from mytable a
order by id;
Of course, this only works where you're able to order rownums in the same (or opposite) order as the order of the ids.
If you're selecting a proper subset of rows, of course you need to apply the same predicate to the whole select and to the subquery:
select a.*,
(select count(*) from table b where b.id <= a.id and b.foo = 'X') as rownum
from table a where a.foo = 'X'
order by id;
Obviously, this is not particularly efficient.
Based on my understanding, you'd need to use ranking functions and/or the TOP clause. The SQL Server features are specific, the Oracle one combines the 2 concepts.
The ranking function is simple: here is why you'd use TOP.
Note: you can't WHERE on ROWNUMBER directly...
'Orable:
select
column_1, column_2
from
table_1, table_2
where
field_3 = 'some value'
and rownum < 5
--MSSQL:
select top 4
column_1, column_2
from
table_1, table_2
where
field_3 = 'some value'

Resources