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 2000 Forums
 SQL Server Development (2000)
 Top 1 row per customer

Author  Topic 

simondeutsch
Aged Yak Warrior

547 Posts

Posted - 2002-05-28 : 16:11:41
Hiya!
How do I select 1 row per customer from the Orders table? Top 1 will actually only return 1 row, while what I'd like is 1 row per customer.
(But not a summary row- No Group By!) Sort of like Line 1 from each order, except some orders might not have a line 1 as it may have been deleted, with only lines 2-5 left.

Sarah Berger MCSD

setbasedisthetruepath
Used SQL Salesman

992 Posts

Posted - 2002-05-28 : 16:14:48
what's the defining attribute of the one row you want per customer per order? min(line #)?

quote:

Hiya!
How do I select 1 row per customer from the Orders table? Top 1 will actually only return 1 row, while what I'd like is 1 row per customer.
(But not a summary row- No Group By!) Sort of like Line 1 from each order, except some orders might not have a line 1 as it may have been deleted, with only lines 2-5 left.

Sarah Berger MCSD



setBasedIsTheTruepath
<O>
Go to Top of Page

simondeutsch
Aged Yak Warrior

547 Posts

Posted - 2002-05-28 : 17:05:49
quote:
what's the defining attribute of the one row you want per customer per order? min(line #)?

Yes. But does it make much sense to have a subquery in the WHERE clause "WHERE Line = (SELECT Min(Line) FROM .....)"? Or is there a better way to do this?

Sarah Berger MCSD
Go to Top of Page

Merkin
Funky Drop Bear Fearing SQL Dude!

4970 Posts

Posted - 2002-05-28 : 19:07:11
Sarah

There is an answer that setbased looks like he is going to give you, you just have to answer his question first

Damian
Go to Top of Page

simondeutsch
Aged Yak Warrior

547 Posts

Posted - 2002-05-29 : 10:48:54
quote:

Sarah

There is an answer that setbased looks like he is going to give you, you just have to answer his question first

Damian



I did answer yes. Would you like a different answer, or I should just plain shut up and not ask more questions in the same breath as my answer?

Sarah Berger MCSD
Go to Top of Page

setbasedisthetruepath
Used SQL Salesman

992 Posts

Posted - 2002-05-29 : 11:05:10
Relax ...

I don't believe Merkin was trying to antagonize you, I certainly wasn't. What I was trying to do was ask a question that would lead you down the right path when answered. He picked up on that too I think.

You can write the query with an IN, or a join, or a correlated sub-query with a HAVING. Any of those ways will work. Let me know if you want me to elaborate on that at all. If so post the DDL.

setBasedIsTheTruepath
<O>
Go to Top of Page

simondeutsch
Aged Yak Warrior

547 Posts

Posted - 2002-05-29 : 12:06:10
Hi, SetBased,
Have no fear, I'm not antagonized, and I was just kidding. I wanted to edit my post and insert a smiley face to show it, but the Edit Post icon seems to have run away.
I did realized that your question had a clue in it, which is why I answered as I did. Here's the select statement:

SELECT (CASE WHEN GroupName IS NULL THEN 'Dr. ' + RTRIM (D.FirstName) + ' ' + D.LastName ELSE GroupName END) AS DrName, D.Address AS DrAddress, (RTRIM (D.City) + ', ' + D.State + ' ' + D.ZipCode) AS DrCSZ, D.Phone AS DrPhone, P.Account, (RTRIM (P.FirstName) + ' ' + P.LastName) AS PtName, P.Address, (RTRIM (P.City) + ', ' + P.State + ' ' + P.ZipCode) AS CSZ, V.VoucherNo, VD.ServiceDate, VD.ProcCode, (SELECT TOP 1 Description FROM CPTCodes WHERE Code = VD.ProcCode) AS CPTDesc, VD.Charge, VD.AmountPaid, VD.AdjAmount, VD.SingleBalance, (CASE WHEN DATEDIFF (dd, VD.ServiceDate,getdate()) < 30 THEN SingleBalance ELSE 0 END) AS '029', (CASE WHEN DATEDIFF (dd, VD.ServiceDate,getdate()) BETWEEN 30 AND 59 THEN SingleBalance ELSE 0 END) AS '3059', (CASE WHEN DATEDIFF (dd, VD.ServiceDate,getdate()) BETWEEN 60 AND 89 THEN SingleBalance ELSE 0 END) AS '6089', (CASE WHEN DATEDIFF (dd, VD.ServiceDate,getdate()) BETWEEN 90 AND 120 THEN SingleBalance ELSE 0 END) AS '90119', (CASE WHEN DATEDIFF (dd, VD.ServiceDate,getdate()) > 120 THEN SingleBalance ELSE 0 END) AS '120', getdate() AS Today,(SELECT COUNT(Voucherno) FROM Submissions WHERE VoucherNo = V.VoucherNo AND Submittype = 'Statement' AND EXISTS (SELECT VoucherNo FROM Vouchers WHERE VoucherNo = V.VoucherNo AND TotBal > 0)) AS NoticeNo, PtNote = 'Your Account Is ' + CASE WHEN DATEDIFF(dd,VD.ServiceDate,getdate()) > 120 THEN '120+ Days' ELSE (CASE WHEN DATEDIFF(dd,VD.ServiceDate,getdate()) BETWEEN 90 AND 119 THEN '90 Days' ELSE (CASE WHEN DATEDIFF(dd,VD.ServiceDate,getdate()) BETWEEN 60 AND 89 THEn '60 Days' ELSE (CASE WHEN DATEDIFF(dd,VD.ServiceDate,getdate()) BETWEEN 30 AND 59 THEN '30 Days' ELSE 'Less Than 30 Days' END)END)END)END + ' Overdue. Please Pay Up.' FROM Patients P INNER JOIN (Doctors D INNER JOIN (Vouchers V INNER JOIN VouchersDetail VD ON VD.Voucher = V.VoucherNo AND VD.ServiceDate BETWEEN '1/1/1900' AND getdate() AND V.Printed = 1 AND VD.SingleBalance > 0) ON V.DrCode = D.Code) ON P.ID = VD.PatID AND P.Account BETWEEN 0 AND 999999999 ORDER BY P.Lastname, P.Firstname, VoucherNo,Linenumber

This returns all lines for a patient, which is fine sometimes. Sometimes I need only 1 line, with all the fields in this query.

quote:
You can write the query with an IN, or a join, or a correlated sub-query with a HAVING.

Dunno about an IN - There's really no way to know what the linenumbers are, as aforementioned. There may be an order whose first n lines were deleted, and linenumbers do not reorder. How could a JOIN be used here? HAVING also sounds good, but how to use it without GROUP BY?

If you'd like the table structure DDL, I can post it, but there's alot of unnecessary fields in there.

Sarah Berger MCSD
Go to Top of Page

setbasedisthetruepath
Used SQL Salesman

992 Posts

Posted - 2002-05-29 : 13:17:44
wow ... that's quite a select.

I'll admit to not having fully digested it all, but it looks (?) like what you need to do join to the first line for a patient in VoucherDetails, rather than the whole table.

setBasedIsTheTruepath
<O>
Go to Top of Page

simondeutsch
Aged Yak Warrior

547 Posts

Posted - 2002-05-29 : 13:40:37
Its bark is worse than its bite...
The long CASE statements only calculate patient balance aging twice, once for summing, and once for a message. You can ignore that junk. Otherwise, the select is quite benign, only 4 tables.

quote:
...FROM Patients P INNER JOIN (Doctors D INNER JOIN (Vouchers V INNER JOIN VouchersDetail VD ON VD.Voucher = V.VoucherNo AND VD.ServiceDate BETWEEN '1/1/1900' AND getdate() AND V.Printed = 1 AND VD.SingleBalance > 0) ON V.DrCode = D.Code) ON P.ID = VD.PatID AND P.Account BETWEEN 0 AND 999999999...


Are you suggesting I should add a correlated subquery to the innermost join "(Vouchers V INNER JOIN VouchersDetail VD ON VD.Voucher = V.VoucherNo AND VD.ServiceDate BETWEEN '1/1/1900' AND getdate() AND V.Printed = 1 AND VD.SingleBalance > 0 AND VD.LineNumber = (SELECT MIN(Linenumber) FROM VouchersDetail WHERE Voucher = V.VoucherNo))", because otherwise I see no way to join to a single line only,since linenumber exists only in the Vouchersdetail table, not the others.

Sarah Berger MCSD
Go to Top of Page

setbasedisthetruepath
Used SQL Salesman

992 Posts

Posted - 2002-05-29 : 13:41:32
that sounds right.

setBasedIsTheTruepath
<O>
Go to Top of Page
   

- Advertisement -