views:

1131

answers:

3

I have two tables: "user" -> "order"

TABLE: user

user_id
-----------
    u1
    u2

TABLE: order

order_id | user_id | flag
-------------------------
    o1   |    u1   |  fA
    o2   |    u2   |  fB

Y need obtain all users counting how many times have orders with flag 'fA'

RESULTS WHAT I NEED:

user_id | orders
----------------
   u1   |   1
   u2   |   0

I TRY:

SELECT
    u.user_id,
    COUNT(o.order_id) AS orders
FROM
    `user` AS u LEFT JOIN
    `order` AS o USING (user_id)
WHERE
    o.flag IS NULL OR
    o.flag IN ('fA')
GROUP BY
    u.user_id;

But, this query is excluding user=u2 because he don't have an order with flag fA; I need the user=u2 appear with orders=0

Maybe something like that:

SELECT
    u.user_id,
    COUNT(o.order_id IF o.flag IN('fA')) OR 0 AS count ...

Tables and data:

CREATE TABLE `user` (user_id VARCHAR(2) NULL);
CREATE TABLE `order` (order_id VARCHAR(2) NULL,user_id VARCHAR(2) NULL,flag VARCHAR(2) NULL);
INSERT INTO `user` VALUES ('u1'), ('u2');
INSERT INTO `order` VALUES ('o1','u1','fA'),('o2','u2','fB');
+3  A: 

You need to use a left outer join instead of left join

SELECT
    u.user_id,
    COUNT(o.order_id) AS orders
FROM
    `user` AS u LEFT OUTER JOIN
    `order` AS o USING (user_id)
WHERE
    o.flag IS NULL OR
    o.flag IN ('fA')
GROUP BY
    u.user_id;
catalpa
Hi, I don't know how to use OUTER JOINs, find out more about it, thanks for introducing me
A: 

You can try using a CASE statement. I don't have MYSQL here today so I can validate the syntax, but it should be close to this:

  SELECT   u.user_id,
             CASE
                WHEN (SELECT COUNT (*)
                        FROM ORDER z
                       WHERE z.user_id = USER.user_id) > 0
                   THEN COUNT (*)
                ELSE 0
             END CASE AS cnt
        FROM USER
    GROUP BY USER.user_id;
northpole
A: 

This query will work:

SELECT
    u.user_id,
    COUNT(o.order_id) AS orders
FROM
    `user` AS u LEFT OUTER JOIN
    (SELECT user_id, order_id FROM `order` WHERE flag IS NULL OR flag IN ('fA')) as o
    USING (user_id)
GROUP BY
    u.user_id;
Nadia Alramli
Thank you very much, works good; but, is necesary to use LEFT OUTER JOIN?, because with simple LEFT JOIN works fine.This is additional: Is there a way to do with simple SELECT query without sub-selects?
I'm using LEFT OUTER JOIN in case there is a user that has no entries in the order table yet. Is there a reason why you don't prefer a sub-query solution?
Nadia Alramli
Well, I wrote my little db abstraction layer for php, work this way:$users = new users();$results = $user->select(array(//another parameters...'JOIN' => 'array_key_where_previosly_i_defined_join_rules,another_key'));The parameter 'JOIN' just accept simple 'keys' with additional ALIAS and 'LEFT','RIGHT' modificators, no accept a customo SELECT as a table. (Example: 'JOIN'=>'LEFT:key,RIGHT:key AS alias').But I think y solve de problem, I create a "view" with custom select join, and now I can create a key for this "view table".I'm not sure to diferentiate LEFT [OUTER] JOIN. Thanks again
Lets see, if I add another user "u3" and this user don't have a row in order table. The querys "LEFT JOIN" and "LEFT OUTER JOIN" returns the same correct result. :S
I'm glad the solution works. About outer of inner join you can refer to the documentation for more details http://dev.mysql.com/doc/refman/5.0/en/join.html
Nadia Alramli