nested select in sql server 2008 - sql

I save user logins in a table that named loginstats, I want to retrieve last login of every users, I use these code but I meet some error, What is my mistake?
select *
from loginStats
where id in (
select distinct username, MAX(id) as id
from loginStats
group by username)

You are doing id IN, but are trying to compare it to multiple columns. Try this instead:
SELECT A.*
FROM LoginStats A
INNER JOIN (SELECT DISTINCT username, MAX(id) as id
FROM loginStats
GROUP BY username) B
ON A.username = B.username AND A.id = B.id

select *
from loginStats
where id in (
select distinct MAX(id) as id
from loginStats
group by username)
You can't have multiple field outputs in your IN subquery.

Or you could also do this like this:
;WITH CTE
AS
(
SELECT
RANK() OVER(
PARTITION BY loginStats.username
ORDER BY loginStats.id DESC
) AS iRank,
loginStats.*
FROM
loginStats
)
SELECT
*
FROM
CTE
WHERE
CTE.iRank=1
Here is some information how to use the rank function and how it is applied.
Here is some information on msdn about the rank function.
Here is some information about cte function and usage
Here is some information about With clause and how it is used
Hope it helps you understand

The mistake is that in the IN clause only one column can be specified and you are specifying two: username and id.

You're selecting two fields, where you should only return one. This correlated subquery should work for you:
select *
from loginStats AS a
where id = (
select MAX(id) as id
from loginStats AS b
where b.username = a.username)

Related

Listing multiple columns in a single row in SQL

(select ID,EXTERNAL_TRANSACTION_ID,EXTERNAL_TRANSACTION_TYPE,ROW_NUMBER() OVER(PARTITION BY EXTERNAL_TRANSACTION_ID ORDER BY ID ) AS SEQNUM
from AC_POS_TRANSACTION_TRK aptt WHERE [RESULT] ='Success'
GROUP BY ID, EXTERNAL_TRANSACTION_ID,EXTERNAL_TRANSACTION_TYPE )
Hello,
On above query, I want to get rows of transaction id's which has seqnum=1 and seqnum=2
But if that transaction id has no second row (seqnum=2), I dont want to get any row for that transaction id.
Thanks!!
Something like this
Not 100% sure if this is correct without you table definition, but my understanding is that you want to EXCLUDE records if that record has an entry with seqnum=2 -- you can't use a where clause alone because that would still return seqnum = 1.
You can use an exists /not exists or in/not in clause like this
(select ID,EXTERNAL_TRANSACTION_ID,EXTERNAL_TRANSACTION_TYPE,ROW_NUMBER() OVER(PARTITION BY EXTERNAL_TRANSACTION_ID ORDER BY ID ) AS SEQNUM
from AC_POS_TRANSACTION_TRK aptt WHERE [RESULT] ='Success'
and not exists ( select 1 from AC_POS_TRANSACTION_TRK a where a.id = aptt.id
and a.seqnum = 2)
GROUP BY ID, EXTERNAL_TRANSACTION_ID,EXTERNAL_TRANSACTION_TYPE )
basically what this does is it excludes records if a record exists as specified in the NOT EXISTS query.
One option you can try is to add a count of rows per group using the same partioning critera and then filter accordingly. Not entirely sure about your query without seeing it in context and with sample data - there's no aggregation so why use group by?
However can you try something along these lines
select * from (
select ID,EXTERNAL_TRANSACTION_ID,EXTERNAL_TRANSACTION_TYPE,
Row_Number() over(partition by EXTERNAL_TRANSACTION_ID order by ID) as SEQNUM,
Count(*) over(partition by EXTERNAL_TRANSACTION_ID) Qty
from AC_POS_TRANSACTION_TRK
where [RESULT] ='Success'
)x
where SEQNUM in (1,2) and Qty>1
This should do the job.
With Qry As (
-- Your original query goes here
),
Select Qry.*
From Qry
Where Exists (
Select *
From Qry Qry1
Where Qry1.EXTERNAL_TRANSACTION_ID = Qry.EXTERNAL_TRANSACTION_ID
And Qry1.SEQNUM = 1
)
And Exists (
Select *
From Qry Qry2
Where Qry2.EXTERNAL_TRANSACTION_ID = Qry.EXTERNAL_TRANSACTION_ID
And Qry2.SEQNUM = 2
)
BTW, your original query looks problematic to me, specifically I think that instead of a GROUP BY columns those columns should be in the PARTITION BY clause of the OVER statement, but without knowing more about the table structures and what you're trying to achieve, I could not say for sure.

Data based on first row value in sql server

I have a table Activity having data like below.It contains multiple rows of CreatedBY like IVR,Raghu and IT.
But I need to get the data only when the first row of CreatedBY='IVR'.
This following query will return firstcreated row for each user (CreatedBy)-
SELECT * FROM
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY CreatedBy ORDER BY CreatedBy,[Date And Time]) RN
FROM your_table
)A
WHERE RN = 1
I suspect you want the first row per ticket_no. At least, that makes more sense as a query.
If so, in SQL Server, you can use a correlated subquery:
select a.*
from activity a
where a.createdby = 'Raghu' and
a.datetime = (select min(a2.datetime)
from activity a2
where a2.ticket_no = a.ticket_no
);
use exists
select a.*
from table a where createdby='IVR'
and datetime in
(select min(datetime) from table b where a.ticketno=b.ticketno
and createdby='IVR')

solution for writing query

I have a match table with winningteamid and stadiumid as attributes,
I need to retrieve the winningteamid which has won all its games in the same stadium.
I tried this, and I'm getting additional unwanted rows:
select winningteamid
from match
group by winningteamid
having count(winningteamid) in (
select count(*) from match group by (winningteamid,stadiumid)
Try this please (please write which RDBMS you are using):
with cte as (
select winningteamid, stadiumid, count(stadiumid) over (partition by winningteamid) as count
from match
group by winningteamid, stadiumid
)
select * from cte where count = 1;
You should use this:
SELECT MAX(winningteamid)
FROM (
SELECT DISTINCT winningteamid, stadiumid
FROM match
)
GROUP BY stadiumid
HAVING COUNT(*) = 1;
I suppose it's as easy as using HAVING to verify only one distinct stadiumid:
select winningteamid
from match
group by winningteamid
having count(distinct stadiumid) = 1

Selecting TOP 1 Columns where duplicate exists and selecting all where no duplicate exists

Given the list of Names, Accounts and Positions I am trying to:
Select the 1st position where there are more than 1 records with the same Name and Account
If there is only 1 record with the Name and Account, then select details.
My current query looks like the following:
SELECT *
FROM CTE cte1
JOIN
(
SELECT Name, OppName FROM CTE GROUP BY Name, OppName HAVING COUNT(Name)>1
) as cte2
on cte2.Name = cte1.Name and cte2.OppName = cte1.OppName
ORDER BY cte1.OppName, cte1.Name
I have not posted the rest of the CTE query as it is way to long.
However, this is only providing me with the results where the Name and Accounts are the same and the Positions are different.
I.E. If Oera worked at Christie's as a Sales Analyst and a Developer It would only Select the record where Oera worked at Christie's as a Developer.
How do I modify this query accordingly?
Are you looking for something like this?
SELECT *
FROM CTE AS cte1
JOIN
(
SELECT Name, OppName,COUNT(Name) PARTITION BY (Name,OppName) cnt
FROM CTE
) AS cte2
ON cte2.Name = cte1.Name and cte2.OppName = cte1.OppName
WHERE cnt > 1
ORDER BY cte1.OppName, cte1.Name

Select a NON-DISTINCT column in a query that return distincts rows

The following query returns the results that I need but I have to add the ID of the row to then update it. If I add the ID directly in the select statement it will return me more results then I need because each ID is unique so the DISTINCT statement see the line as unique.
SELECT DISTINCT ucpse.MemberID, ucpse.ProductID, ucpse.UserID
FROM UserCustomerProductSalaryExceptions as ucpse
WHERE EXISTS (SELECT NULL
FROM UserCustomerProductSalaryExceptions as upcse2
WHERE ucpse.userid = upcse2.userid AND ucpse.MemberID = upcse2.MemberID AND ucpse.ProductID = upcse2.ProductID
GROUP BY upcse2.UserID, upcse2.memberid, upcse2.productid
HAVING COUNT(UserID) >= 2
)
So basically I need to add ucpse.ID in the Select statement while keeping DISTINCT values for MemberID,ProductID and UserID.
Any Ideas ?
Thank you
According to you comment:
If the data has been duplicated 67 times for a given employee with a given product and a given client, I need to keep only one of thoses records. It's not important which one, so this is why I use DISTINC to obtain unique combinaison of given employee with a given product and a given client.
You can use MIN() or MAX() and GROUP BY instead of DISTINCT
SELECT MAX(ucpse.ID) AS ID, ucpse.MemberID, ucpse.ProductID, ucpse.UserID
FROM UserCustomerProductSalaryExceptions as ucpse
WHERE EXISTS (SELECT NULL
FROM UserCustomerProductSalaryExceptions as upcse2
WHERE ucpse.userid = upcse2.userid AND ucpse.MemberID = upcse2.MemberID AND ucpse.ProductID = upcse2.ProductID
GROUP BY upcse2.UserID, upcse2.memberid, upcse2.productid
HAVING COUNT(UserID) >= 2
)
GROUP BY ucpse.MemberID, ucpse.ProductID, ucpse.UserID
UPDATE:
From you comments I think the below query is what you need
DELETE FROM UserCustomerProductSalaryExceptions
WHERE ID NOT IN ( SELECT MAX(ucpse.ID) AS ID
FROM #UserCustomerProductSalaryExceptions
GROUP BY ucpse.MemberID, ucpse.ProductID, ucpse.UserID
HAVING COUNT(ucpse.ID) >= 2
)
If all you want is to delete the duplicates, this will do it:
WITH X AS
(SELECT ID,
ROW_NUMBER() OVER (PARTITION BY MemberID, ProductID, UserID ORDER BY ID) AS DupRowNum<br
FROM UserCustomerProductSalaryExceptions
)
DELETE X WHERE DupRowNum > 1
ID's not necessary - try:
UPDATE uu SET
<your settings here>
FROM UserCustomerProductSalaryExceptions uu
JOIN ( <paste your entire query above here>
) uc ON uc.MemberID=uu.MemberId AND uc.ProductID=uu.ProductId AND uc.UserID=uu.UserId
From the sound of your data structure (which I would STRONGLY advise normalizing as soon as possible), it sounds like you should be updating all the records. It sounds as if each duplicate is important because it contains some information about an employee's relation to a customer or product.
I would probably update all the records. Try this:
UPDATE UCPSE
SET
--Do your updates here
FROM UserCustomerProductSalaryExceptions as ucpse
JOIN
(
SELECT UserID, MemberID, ProductID
FROM UserCustomerProductSalaryExceptions
GROUP BY UserID, MemberID, ProductID
HAVING COUNT(UserID) >= 2
) T
ON ucpse.UserID = T.UserID AND ucpse.MemberID = T.MemberID AND ucpse.ProductID = T.ProductID