How to convert this query to SQL Server 2000 syntax - sql

I am running this query to SQL Server 2008+ but it doesn't work on SQL Server 2000.
and i need this to execute.
WITH CTE AS (
SELECT
custnum,
custname,
RN = ROW_NUMBER() OVER( PARTITION BY custnum, custname ORDER BY custnum )
FROM
cust
)
SELECT
*
FROM
CTE
WHERE RN > 1
thank you so much for your help!

Prior to SQL Server 2005, this problem domain was solved with ordered inserts into a #temp table with an IDENTITY column to generate the sequence number. This would solve RANK() and ROW_NUMBER() requirements.
E.g.:
-- Create empty temp table
SELECT custnum, custname, IDENTITY(INT, 1, 1) as RN
INTO #cust
FROM cust
WHERE 0 = 1
-- Populate with ORDER BY, to generate ascending RN
INSERT INTO #cust
(custnum, custname)
SELECT
custnum, custname
FROM
cust
ORDER BY
custnum, custname
At that point, you can query MIN() for each custnum/custname grouping and use that as you'd use the CTE.
However ... is ROW_NUMBER() really what you want here ? Seems like you'd want RANK(), not ROW_NUMBER().

See if this works
select custnum,custname from
(
select (select count(*) from cust as t1 where t1.custnum<=t2.custnum) as sno,
custnum,custname from cust as t2
) as t
where sno>1

Related

Second minimum value for every customer

I am using MySQL database. So, there are two columns I am working on, CustomerId, and OrderDate. I want to find a second-order date (2nd minimum order date) for each customer.
If you are using MySQL 8+, then ROW_NUMBER can be used here:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY OrderDate) rn
FROM yourTable
)
SELECT CustomerId, OrderDate
FROM cte
WHERE rn = 2;
I would recommend using dense_rank as it can give you correct result even if there is duplicate order_date as follows:
SELECT * FROM
(SELECT t.*, DENSE_RANK() OVER (PARTITION BY CustomerId ORDER BY OrderDate) dr
FROM yourTable t
) t where dr = 2;
You can use corelated sub-query as follows if your MySQL version do not support analytical functions as follows:
SELECT T.*
FROM YOURTABLE T
WHERE 1 = (
SELECT COUNT(DISTINCT ORDER_DATE)
FROM YOURTABLE TT
WHERE TT.ORDER_DATE > T.ORDER_DATE
)
I would use a subquery like this:
select o.*
from orders o
where o.order_date = (select o2.order_date
from orders o2
where o2.customer_id = o.customer_id
order by o2.order_date
limit 1 offset 1
);
The subquery is a correlated subquery that returns the second date. If you want the second date with other columns, it can be moved to the select.
With an index on (customer_id, order_date), this is likely to be the fastest solution.
This assumes that there is one row per date (or that if there are multiple rows, "second" can be the earliest date). If you want the second distinct date then use select distinct int he subquery -- however select distinct and group by would incur additional overhead.

Perform pivot operation on the table but facing problem as it requires multiple aggregate function to segregate dates into two columns

I have this table named hotel which contains EmpId and their corresponding [check-in/out] column in datetime format.
Now, I want the data in table to look like this.
I have tried following simple query and it's working correctly:
select EmpId, min([Check-in/out]) as Checkin, max([Check-in/out]) as Checkout
from [dbo].[hotel]
group by EmpId;
But i want to do it using pivot operator in sql server. I have tried the following query but it's incorrect:
select EmpId, Min([Check-in/out]) AS Checkin, Max([Check-in/out]) AS Checkout
FROM
(select EmpId, [Check-in/out] from [dbo].[hotel]) AS SourceTable
PIVOT
(
min([Check-in/out])
FOR [Check-in/out] IN(Checkin)
)AS PivotTable1
PIVOT
(
max([Check-in/out])
FOR [Check-in/out] IN(Checkout)
)AS PivotTable2;
Here again my comment as answer with an example:
I suggest using cte / subqueries in order to approach this problem... first of all, select EmpID, time and rownumber (partition by empid and order by time) - this gives you all checkins with odd rownumber and all checkouts with even rownumber. Next - basing on this query - select empid, time and CASE WHEN rownumber%2=0 THEN 'CHECKOUT' ELSE 'CHECKIN' END AS CheckInOut... this result again can be used in your pivot statement
Example:
WITH cte AS(
SELECT *, ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY CheckInOut) rn
FROM T1
),
cteInOut AS(
SELECT EmpID, CheckInOut, CASE WHEN rn%2 = 0 THEN N'CheckOut' ELSE N'CheckIn' END AS CheckInOutState
FROM cte
),
cteInOuntSrt AS(
SELECT EmpID, CheckInOut, CheckInOutState, ROW_NUMBER() OVER (PARTITION BY EmpID, CheckInOutState ORDER BY CheckInOut) rn1
FROM cteInOut
)
select EmpID, rn1 AS CheckIndIdx, CheckIn, CheckOut
from cteInOuntSrt
pivot
(
min(CheckInOut)
for CheckInOutState in ([CheckIn], [CheckOut])
) piv
ORDER BY 1, 2;
fiddle: http://sqlfiddle.com/#!18/af6f3/1/1
If the values line up, you can use lead() and row_number():
select c.empid, checkin, checkout
from (select c.*, [Check-in/out] as checkin,
lead([Check-in/out]) over (partition by empid order by [Check-in/out]) as checkout,
row_number() over (partition by empid order by [Check-in/out]) as seqnum
from [Check-in/out] c
) c
where seqnum % 2 = 1;
This does the following calculations:
Calculate the next date/time value.
Enumerate the rows, starting the count from 1.
Taking the odd-numbered rows. These are the check ins.

Filter the table with latest date having duplicate OrderId

I have following table:
I need to filter out the rows for which start date is latest corresponding to its order id .With reference to given table row no 2 and 3 should be the output.
As row 1 and row 2 has same order id and order date but start date is later than first row. And same goes with row number 3 and 4 hence I need to take out row no 3 . I am trying to write the query in SQL server. Any help is appreciated.Please let me know if you need more details.Apologies for poor English
You can do this easily with a ROW_NUMBER() windowed function:
;With Cte As
(
Select *,
Row_Number() Over (Partition By OrderId Order By StartDate Desc) RN
From YourTable
)
Select *
From Cte
Where RN = 1
But I question the StartDate datatype. It looks like these are being stored as VARCHAR. If that is the case, you need to CONVERT the value to a DATETIME:
;With Cte As
(
Select *,
Row_Number() Over (Partition By OrderId
Order By Convert(DateTime, StartDate) Desc) RN
From YourTable
)
Select *
From Cte
Where RN = 1
Another way using a derived table.
select
t.*
from
YourTable t
inner join
(select OrderId, max(StartDate) dt
from YourTable
group by OrderId) t2 on t2.dt = t.StartDate and t2.OrderId = t.OrderId

How to use distinct when you select multiple column in SQL

I have use simple inner join statement and getting result into CTE table. I want to select distinct 'ServiceId' from CTE. I have following query
SELECT DISTINCT(ServicesId), ServiceNo, ServiceDate, DealerCode FROM CTE_Temp
Suppose there are duplicate entries of ServiceId in CTE then I want to select first entry only and ignore rest of them.
You can use ROW_NUMBER() OVER() for this. Just replace the column in the ORDER BY to define what's first.
;WITH AnotherCTE AS(
SELECT
ServicesId, ServiceNo, ServiceDate, DealerCode,
RN = ROW_NUMBER() OVER(PARTITION BY ServicesID ORDER BY ServiceDate DESC)
FROM CTE_Temp
)
SELECT
ServicesId, ServiceNo, ServiceDate, DealerCode
FROM AnotherCTE
WHERE RN = 1

How to fill `[Order]` column by order number in SQL Server?

How to fill [Order] column by order number in SQL Server 2000?
For example, I have a SQL:
select Id, Tilte
from Tbl
order by Date
I need to write order number from this query to column [Order] of Tbl table.
How to do this?
Thanks a lot for the help!
You can use ROW_NUMBER:
WITH CTE AS
(
SELECT Id, Title, [Order]
, OrderNumber = ROW_NUMBER() OVER (ORDER BY Date)
FROM Tbl
)
UPDATE CTE SET [Order] = CTE.OrderNumber;
Here's a fiddle: http://sqlfiddle.com/#!3/8831d/2/0