Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Get users only once

Author  Topic 

Heinz23
Yak Posting Veteran

84 Posts

Posted - 2008-07-13 : 19:02:27
Hi all,
I have a user table and a quantity table. Each user orders some products. Now I want to display the top 3 buyers from the last 7 days. Mainly it's easy but my problem: A user might have 2 records within the last 7 days, one from friday and the other from tuesday. If both would be in the top 3 I only want to see it once (but NOT added together).

Example (Username - Ordered units - Order date):
User A - 400 units - 1. Jan
User B - 350 units - 1. Jan
User C - 200 units - 1. Jan
User A - 500 units - 4. Jan
User C - 250 units - 4. Jan
User D - 300 units - 5. Jan

The query on 5. Jan should return the following top 3:
User A - 500 units
User B - 350 units
User D - 300 units

So orders of User A (400 + 500) and also User C (200 + 250) are NOT summed up so User C should not appear in the list even though he has ordered more units than e.g. User B (450 <-> 350).

My current script:

SELECT TOP 3 Users.UserID, Users.Username, Orders.OrderedUnits, Orders.OrderDate
FROM Users INNER JOIN
Orders ON Users.UserID = Orders.UserID
WHERE (DATEDIFF(day, Matches.MatchDate, GETDATE()) <= 7)
ORDER BY Orders.OrderedUnits

Unfortunately the script returns:
User A - 500 units
User A - 400 units
User B - 350 units

How could I modify the script so user A is only used once? Many thanks!

sodeep
Master Smack Fu Yak Hacker

7174 Posts

Posted - 2008-07-13 : 19:33:22


May be this:

quote:
Originally posted by Heinz23

Hi all,
I have a user table and a quantity table. Each user orders some products. Now I want to display the top 3 buyers from the last 7 days. Mainly it's easy but my problem: A user might have 2 records within the last 7 days, one from friday and the other from tuesday. If both would be in the top 3 I only want to see it once (but NOT added together).

Example (Username - Ordered units - Order date):
User A - 400 units - 1. Jan
User B - 350 units - 1. Jan
User C - 200 units - 1. Jan
User A - 500 units - 4. Jan
User C - 250 units - 4. Jan
User D - 300 units - 5. Jan

The query on 5. Jan should return the following top 3:
User A - 500 units
User B - 350 units
User D - 300 units

So orders of User A (400 + 500) and also User C (200 + 250) are NOT summed up so User C should not appear in the list even though he has ordered more units than e.g. User B (450 <-> 350).

My current script:

SELECT TOP 3 Users.UserID, Users.Username, Max(Orders.OrderedUnits), Orders.OrderDate
FROM Users INNER JOIN Orders ON Users.UserID = Orders.UserID
WHERE (DATEDIFF(day, Matches.MatchDate, GETDATE()) <= 7)
Group by Users.UserID,Users.Username, Orders.OrderDate
ORDER BY Orders.OrderedUnits

Unfortunately the script returns:
User A - 500 units
User A - 400 units
User B - 350 units

How could I modify the script so user A is only used once? Many thanks!


Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-07-14 : 00:46:11
[code]SELECT t.Username,t.OrderedUnits
FROM
(
SELECT ROW_NUMBER() OVER(ORDER BY OrderedUnits DESC) AS Seq,
ROW_NUMBER() OVER (PARTITION BY Username ORDER BY OrderedUnits DESC) AS USeq,
*
FROM YourTable) t
WHERE t.USeq=1
AND t.Seq<=3
AND t.MatchDate> DATEADD(d,DATEDIFF(d,0,GETDATE()),-7)[/code]
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2008-07-14 : 03:34:14
[code]
SELECT TOP 3
UserID,
UserName,
OrderedUnits,
OrderDate
FROM (
SELECT Users.UserID,
Users.Username,
Orders.OrderedUnits,
Orders.OrderDate,
ROW_NUMBER() OVER (PARTITION BY Users.UserID ORDER BY Orders.OrderedUnits DESC) AS RecID
FROM Users
INNER JOIN Orders ON Orders.UserID = Users.UserID
WHERE Matches.MatchDate >= DATEDIFF(DAY, '19000107', GETDATE())
AND Matches.MatchDate < DATEDIFF(DAY, '19000101', GETDATE())
) AS x
WHERE RecID = 1
ORDER BY OrderedUnits DESC[/code]

E 12°55'05.25"
N 56°04'39.16"
Go to Top of Page

Heinz23
Yak Posting Veteran

84 Posts

Posted - 2008-07-14 : 07:32:38
Hi sodeep,

trying your proposal fails with an error that I could not use Orders.OrderedUnits "because it is not contained in either an aggregate function or the GROUP BY clause.". But when I add it to the Group by I have the same result as before.

Hi Visakh16,
seems that in your proposal the JOIN to the Matches-Table is missing (Matches.MatchDate contains the date of the order). I tried to add it on my own but then NO row is returned anymore?

Hi Peso,
your script only returns the rows from UserA?


Hm, maybe I confused you all with the script I included. I've seen that I did not supply information that 'OrderID' should be used to combine both tables, sorry to you all !!

Please let me re-describe my need:

Table 'Orders' has 2 columns: OrderID, OrderDate.
123 - 14.07.2008
456 - 12.07.2008
789 - 02.07.2008
Table 'Units' has 3 columns: OrderID, CustomerName, OrderedUnits.
123 - CustomerA - 300
123 - CustomerB - 230
123 - CustomerC - 350
456 - CustomerB - 250
456 - CustomerC - 350
456 - CustomerD - 400
789 - CustomerE - 800
I want to get the 3 largest order positions from the last 7 days. When I today (14.07.) run the query I need a result set like this:
CustomerD - 400
CustomerC - 350
CustomerA - 300

Many thanks for your help!!
Go to Top of Page

visakh16
Very Important crosS Applying yaK Herder

52326 Posts

Posted - 2008-07-14 : 07:44:18
[code]SELECT t.Username,t.OrderedUnits
FROM
(
SELECT ROW_NUMBER() OVER(ORDER BY OrderedUnits DESC) AS Seq,
ROW_NUMBER() OVER (PARTITION BY Username ORDER BY OrderedUnits DESC) AS USeq,
y.*,m.MatchDate
FROM YourTable y
INNER JOIN Matches m
ON m.Lonkcol=y.Linkcol) t
WHERE t.USeq=1
AND t.Seq<=3
AND t.MatchDate> DATEADD(d,DATEDIFF(d,0,GETDATE()),-7)[/code]
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2008-07-14 : 07:58:53
This is produces exactly what you want.
DECLARE	@Orders TABLE (OrderID INT, OrderDate DATETIME)

SET DATEFORMAT DMY

INSERT @Orders
SELECT 123, '14.07.2008' UNION ALL
SELECT 456, '12.07.2008' UNION ALL
SELECT 789, '02.07.2008'

DECLARE @Units TABLE (OrderID INT, CustomerName VARCHAR(20), OrderedUnits INT)

INSERT @Units
SELECT 123, 'CustomerA', 300 UNION ALL
SELECT 123, 'CustomerB', 230 UNION ALL
SELECT 123, 'CustomerC', 350 UNION ALL
SELECT 456, 'CustomerB', 250 UNION ALL
SELECT 456, 'CustomerC', 350 UNION ALL
SELECT 456, 'CustomerD', 400 UNION ALL
SELECT 789, 'CustomerE', 800

SELECT TOP 3
CustomerName,
OrderedUnits,
OrderDate,
OrderID
FROM (
SELECT u.CustomerName,
u.OrderedUnits,
o.OrderDate,
o.OrderID,
ROW_NUMBER() OVER (PARTITION BY u.CustomerName ORDER BY u.OrderedUnits DESC) AS RecID
FROM @Units AS u
INNER JOIN @Orders AS o ON o.OrderID = u.OrderID
WHERE o.OrderDate >= DATEDIFF(DAY, '19000107', GETDATE())
AND o.OrderDate < DATEDIFF(DAY, '18991231', GETDATE())
) AS x
WHERE RecID = 1
ORDER BY OrderedUnits DESC



E 12°55'05.25"
N 56°04'39.16"
Go to Top of Page

Heinz23
Yak Posting Veteran

84 Posts

Posted - 2008-07-14 : 09:30:35
Hi all,

fascinating! I've now tried Pesos solution and this works very well

Thanks to both of you for your excellent and fast support!
Go to Top of Page
   

- Advertisement -