简体   繁体   中英

Count the number of fields that are not empty in MySQL

I have a database of users where they can send messages to other users (up to four) and the ID of the message they sent is in their user row.

Name    | Email       | Msg1 | Msg2 | Msg3 | Msg4
--------+-------------+------+------+------+-----
Pez     | me@me.com   |  1   |  55  |  42  |  5 
Steve   | fake@me.com |  0   |   0  |   0  |  0 
Leon    | josh@me.com |  3   |   0  |   3  |  5 

How in a MySQL query can I get the amount of those message rows that are not empty or not equal to 0, allowing me to order by that? So it would return

Pez   | 4 Mesasges
Leon  | 3 Messages
Steve | 0 Messages

Im my mind something like:

order by count(!empty(msg1)+!empty(msg2)+!empty(msg3)+!empty(msg4)) 

With normalized tables it could be as simple as

SELECT Count(*) FROM messages WHERE userid=47

But with your schema try something like

SELECT
  name,
  (msg1<>0) + (msg2<>0) + (msg3<>0) + (msg4<>0) as cMessages
FROM
  foo  

edit: Vincent Ramdhanie's answer using if() doesn't rely on MySQL's behaviour to use 0 as false and 1 as true as result of a comparison. I would prefer that.

 select 
     if(msg1 = 0, 0, 1) +
     if(msg2 = 0, 0, 1) +
     if(msg3 = 0, 0, 1) +
     if(msg4 = 0, 0, 1) as NumMsg,Name
 from table

Your best bet would be to normalize your database as follows:

Table users:    (user_id, name, email)
Table messages: (user_id, msg_number, msg_code)

The users table would have user_id as a primary key, while the messages table would have a composite primary key on (user_id, msg_number) . The msg_number field would represent the 1-4 message number (the number you represented in your column names).

The composite primary key would guarantee that each user can only have one message for each msg_number . You may also want to create a check constraint so that msg_number is always <= 4. Finally you may want to define user_id in the messages table as a foreign key to the users table.

Note that if a user did not send a message, you should not have a row in the messages table with msg_code = 0. Instead, you should simply omit the row.

With normalized tables, counting the number of messages for each user would be as easy as:

SELECT    u.name, COUNT(m.msg_number) as num_of_messages
FROM      users u
JOIN      messages m ON (m.user_id = u.user_id)
GROUP BY  u.user_id;

As others have said the right way to solve the problem is to normalize your database.

You can get the counts from the current schema - but its a bit messy:

SELECT name, (SIGN(msg1)+SIGN(msg2)+SIGN(msg3)+SIGN(msg4))
FROM yourtable
ORDER BY (SIGN(msg1)+SIGN(msg2)+SIGN(msg3)+SIGN(msg4)) DESC;

C.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM