select ... count ... inner join statement

select ... count ... inner join statement

am 03.04.2005 19:19:34 von Trym Bagger

Another SQL question for you friendly people out there.

On an ASP page I access a database that contain the following two tables
(simplified here):

Table name: Customers
Columns:
- IDcustomer (primary key)
- Companyname (string)

Table name: Orders

Columns:
IDorder (primary key)
IDcustomer (long integer)
Status (integer)

The first output I wanted - a list indicating the number of order per
customer - was fairly straight-forward:

SELECT C.IDcustomer, C.CompanynameCOUNT(O.IDorder) as c
FROM Customers as as C
INNER JOIN Orders as loan as O
ON CB.IDcustomer = O.IDcustomer
GROUP BY C.IDcustomer, C.Companyname

However, now I want to make list indicating the number of orders which have
been returned (the column Status in Orders contains the value 2 in case the
order has been returned by the customer) by each customer - EVEN IF THAT
NUMBER IS ZERO. I emphasize this last sentence because the above statement
adding "WHERE O.Status = 2" will not do because it will only show customers
which indeed has returned something.

The result should therefore be:

IDcustomer, C
1, Johnson's Hardware Store, 0
2, Paradise Flowers, 0
3, The Red Pub, 2
4, Smith & Sons, 0
(etc)

Any advice would be highly appreciated.

Finally I would like receive recommendations for a good and comprenhensive
book on SQL, containing both real life examples, a complete reference
section, and show differences in implentations for at least Access, MS SQL
and MySQL.

Thanks in advance.

TB

PS: Last week I asked couple of other questions, and did not acknowledge in
time the answers received. Thanks guys, and sorry for not replying earlier.

Re: select ... count ... inner join statement

am 03.04.2005 23:36:45 von reb01501

TB wrote:
> Another SQL question for you friendly people out there.
>
> On an ASP page I access a database that contain the following two
> tables (simplified here):
>
> Table name: Customers
> Columns:
> - IDcustomer (primary key)
> - Companyname (string)
>
> Table name: Orders
>
> Columns:
> IDorder (primary key)
> IDcustomer (long integer)
> Status (integer)
>
> The first output I wanted - a list indicating the number of order per
> customer - was fairly straight-forward:
>
> SELECT C.IDcustomer, C.CompanynameCOUNT(O.IDorder) as c
> FROM Customers as as C
> INNER JOIN Orders as loan as O
> ON CB.IDcustomer = O.IDcustomer
> GROUP BY C.IDcustomer, C.Companyname
>
> However, now I want to make list indicating the number of orders
> which have been returned (the column Status in Orders contains the
> value 2 in case the order has been returned by the customer) by each
> customer - EVEN IF THAT NUMBER IS ZERO. I emphasize this last
> sentence because the above statement adding "WHERE O.Status = 2" will
> not do because it will only show customers which indeed has returned
> something.
> The result should therefore be:
>
> IDcustomer, C
> 1, Johnson's Hardware Store, 0
> 2, Paradise Flowers, 0
> 3, The Red Pub, 2
> 4, Smith & Sons, 0
> (etc)
>
> Any advice would be highly appreciated.

It would help if we knew all the possible values for statusm but given what
you've told us, the solution is as easy as:

WHERE Status IN (0,2)

>
> Finally I would like receive recommendations for a good and
> comprenhensive book on SQL, containing both real life examples, a
> complete reference section, and show differences in implentations for
> at least Access, MS SQL and MySQL.
>

I hope you find one. I've never seen such a beast. :-)
Have you tried searching amazon.com?

Bob Barrows
--
Microsoft MVP - ASP/ASP.NET
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"

Re: select ... count ... inner join statement

am 04.04.2005 00:56:05 von Trym Bagger

> It would help if we knew all the possible values for statusm but given
> what you've told us, the solution is as easy as:
>
> WHERE Status IN (0,2)
>


Status can be either 0,1 or 2.

I have just added the line you proposed to my SQL query, but the result is
precisely want do NOT want. Your addition adds a filter, thus not creating
lines where c is 0, i.e. no occurences of returned order from a particular
customer. I would like the COUNT property to count the number of instances
where status = 2, and when that count is 0, ALSO express that (by a zero).
With the filter you propose, instances that return zero are ommited.


>
> I hope you find one. I've never seen such a beast. :-)
> Have you tried searching amazon.com?
>
> Bob Barrows

I found this book:

"SQL in Easy Steps", written by Mike McGrath.
Amazon link:
http://www.amazon.co.uk/exec/obidos/ASIN/1840782579/ref=ord_ cart_shr/026-8153264-1906838?%5Fencoding=UTF8&m=A3P5ROKL5A1O LE

Any opinions?

Thanks again.

TB

Re: select ... count ... inner join statement

am 04.04.2005 02:02:30 von reb01501

TB wrote:
>> It would help if we knew all the possible values for statusm but
>> given what you've told us, the solution is as easy as:
>>
>> WHERE Status IN (0,2)
>>
>
>
> Status can be either 0,1 or 2.
>
> I have just added the line you proposed to my SQL query, but the
> result is precisely want do NOT want. Your addition adds a filter, thus
> not
> creating lines where c is 0, i.e. no occurences of returned order from a
> particular customer.

It shouldn't. it should count lines where status contains either 0 or 2.

> I would like the COUNT property to count the number of
> instances where status = 2, and when that count is 0, ALSO express that
> (by a
> zero). With the filter you propose, instances that return zero are
> ommited.
>

Oh, I see the problem. There are several ways to do this. Here is one:

SELECT C.IDcustomer, C.Companyname, Totals
FROM Customers AS C LEFT JOIN
(select IDcustomer, count(*) AS Totals
FROM Orders
WHERE status in (0,2)
GROUP BY IDcustomer)
AS O ON C.IDcustomer = O.IDcustomer

Unfortunately, if you really want to see the 0's, you are going to need to
use some non-standard functions

Here is how you would do it in Access:

SELECT C.IDcustomer, C.Companyname, Nz(Totals, 0)
FROM Customers AS C LEFT JOIN
(select IDcustomer, count(*) AS Totals
FROM Orders
WHERE status in (0,2)
GROUP BY IDcustomer)
AS O ON C.IDcustomer = O.IDcustomer

In SQL Server, you would use either the COALESCE or ISNULL function. I have
no idea how it would be done in MySQL

Another way to do it in Access would be:

SELECT C.IDcustomer, C.Companyname,
Sum(Iif(Status=1,0,1)) As Totals
FROM Customers AS C INNER JOIN Orders
AS O ON C.IDcustomer = O.IDcustomer
GROUP BY C.IDcustomer, C.Companyname

In SQL Server, you would use CASE instead of Iif. Again, I don't know what
functions are provided by MySQL.

>> I hope you find one. I've never seen such a beast. :-)
>> Have you tried searching amazon.com?
>>
>
> I found this book:
>
> "SQL in Easy Steps", written by Mike McGrath.
> Amazon link:
> http://www.amazon.co.uk/exec/obidos/ASIN/1840782579/ref=ord_ cart_shr/026-8153264-1906838?%5Fencoding=UTF8&m=A3P5ROKL5A1O LE
>
> Any opinions?

Nope. i've never read it. I don't have a SQL Language book in my library.

Bob Barrows
--
Microsoft MVP - ASP/ASP.NET
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"

Re: select ... count ... inner join statement

am 04.04.2005 09:19:49 von Trym Bagger

> Here is how you would do it in Access:
>
> SELECT C.IDcustomer, C.Companyname, Nz(Totals, 0)
> FROM Customers AS C LEFT JOIN
> (select IDcustomer, count(*) AS Totals
> FROM Orders
> WHERE status in (0,2)
> GROUP BY IDcustomer)
> AS O ON C.IDcustomer = O.IDcustomer

That one does not work. The server returns: "Undefined function 'Nz' in
expression."

> SELECT C.IDcustomer, C.Companyname,
> Sum(Iif(Status=1,0,1)) As Totals
> FROM Customers AS C INNER JOIN Orders
> AS O ON C.IDcustomer = O.IDcustomer
> GROUP BY C.IDcustomer, C.Companyname

That one does work perfectly. Thanks a lot.

TB

Re: select ... count ... inner join statement

am 04.04.2005 12:48:46 von reb01501

TB wrote:
>> Here is how you would do it in Access:
>>
>> SELECT C.IDcustomer, C.Companyname, Nz(Totals, 0)
>> FROM Customers AS C LEFT JOIN
>> (select IDcustomer, count(*) AS Totals
>> FROM Orders
>> WHERE status in (0,2)
>> GROUP BY IDcustomer)
>> AS O ON C.IDcustomer = O.IDcustomer
>
> That one does not work. The server returns: "Undefined function 'Nz'
> in expression."

It works in Access. I forgot Nz was not usable from ASP. Just replace it
with:

Iif(Totals IS Null,0,Totals)

Bob Barrows
--
Microsoft MVP - ASP/ASP.NET
Please reply to the newsgroup. This email account is my spam trap so I
don't check it very often. If you must reply off-line, then remove the
"NO SPAM"

Re: select ... count ... inner join statement

am 04.04.2005 19:41:55 von Trym Bagger

Thanks Bob, as always, you have been very helpful.

TB

"Bob Barrows [MVP]" wrote in message
news:eXwJcPQOFHA.2748@TK2MSFTNGP09.phx.gbl...
> TB wrote:
>>> Here is how you would do it in Access:
>>>
>>> SELECT C.IDcustomer, C.Companyname, Nz(Totals, 0)
>>> FROM Customers AS C LEFT JOIN
>>> (select IDcustomer, count(*) AS Totals
>>> FROM Orders
>>> WHERE status in (0,2)
>>> GROUP BY IDcustomer)
>>> AS O ON C.IDcustomer = O.IDcustomer
>>
>> That one does not work. The server returns: "Undefined function 'Nz'
>> in expression."
>
> It works in Access. I forgot Nz was not usable from ASP. Just replace it
> with:
>
> Iif(Totals IS Null,0,Totals)
>
> Bob Barrows
> --
> Microsoft MVP - ASP/ASP.NET
> Please reply to the newsgroup. This email account is my spam trap so I
> don't check it very often. If you must reply off-line, then remove the
> "NO SPAM"
>