简体   繁体   中英

How do I Count Field Values from a Single Row?

I'm new to PHP and MySQL and am struggling with this... I am collecting form data from a PHP insert page. It is a survey questionnaire. There are 20 questions, and all the answers will either be A , B and C . The table has an id column, and a column for each question ( Q1, Q2, Q3... Q20 ). The data may look something like this;

+------+-----+
|  id  |  1  |
+------+-----+
|  Q1  |  A  |
|  Q2  |  B  |
|  Q3  |  A  |
|  .   |  .  |
|  .   |  .  |
|  .   |  .  |
|  Q20 |  C  |
+------+-----+

Now, what I am trying to do is to count how many values of A , B and C appear in a single row (with id=1 for example).

I've found lots of ways of counting values in multiple columns, but so far have not found a way to count/group values in a single row.

In PHP, you could load the results of the query into an arary, and then use array_count_values to get the count of each answer:

$array = array();

while ($row = $result->fetch_assoc()) {
    $array[] = $row;
}

// print_r(array_count_values($array); 

foreach(array_count_values($array) as $key => $value)
{
     echo 'Answer ' . $key . ' was chosen ' . $value . ' times <br>';
}

Working Fiddle

DISCLAIMER: from memory so may not exactly work.

How about this?

SELECT 1 AS 1, (SELECT COUNT(1) FROM Questions WHERE 1 = 'A') AS A, (SELECT COUNT(1) FROM Questions WHERE 1 = 'B') AS B, (SELECT COUNT(1) FROM Questions WHERE 1 = 'C') AS C

Hope this helps.

Here's how you can do it with a MySQL query:

select id,
  sum(case when `1` = 'A' then 1 else 0 end) as CountA,
  sum(case when `1` = 'B' then 1 else 0 end) as CountB,
  sum(case when `1` = 'C' then 1 else 0 end) as CountC
from SurveyTable
group by id
order by id;

Here's a SQL Fiddle with limited test data.


Addendum . Carlos posted an updated structure, leading to the following answers. Hope these are close :)

This will give you one very wide row with grand totals:

select
  sum(case when Q1 = 'A' then 1 else 0 end) as Q1CountA,
  sum(case when Q1 = 'B' then 1 else 0 end) as Q1CountB,
  sum(case when Q1 = 'C' then 1 else 0 end) as Q1CountC,
  sum(case when Q2 = 'A' then 1 else 0 end) as Q2CountA,
  sum(case when Q2 = 'B' then 1 else 0 end) as Q2CountB,
  sum(case when Q2 = 'C' then 1 else 0 end) as Q2CountC,
  sum(case when Q3 = 'A' then 1 else 0 end) as Q3CountA,
  sum(case when Q3 = 'B' then 1 else 0 end) as Q3CountB,
  sum(case when Q3 = 'C' then 1 else 0 end) as Q3CountC,
  sum(case when Q4 = 'A' then 1 else 0 end) as Q4CountA,
  sum(case when Q4 = 'B' then 1 else 0 end) as Q4CountB,
  sum(case when Q4 = 'C' then 1 else 0 end) as Q4CountC,
  sum(case when Q5 = 'A' then 1 else 0 end) as Q5CountA,
  sum(case when Q5 = 'B' then 1 else 0 end) as Q5CountB,
  sum(case when Q5 = 'C' then 1 else 0 end) as Q5CountC
from SurveyTable;

If you want to get one row per question then try this:

select
  QuestionID,
  sum(case when Answer = 'A' then 1 else 0 end) as CountA,
  sum(case when Answer = 'B' then 1 else 0 end) as CountB,
  sum(case when Answer = 'C' then 1 else 0 end) as CountC
from (
    select 'Question1' as QuestionID, Q1 as Answer from surveytable
    union all select 'Question2', Q2 from surveytable
    union all select 'Question3', Q3 from surveytable
    union all select 'Question4', Q4 from surveytable
    union all select 'Question5', Q5 from surveytable) x
group by QuestionID

There's a Fiddle here .


Another Addendum : Counts needed by ID , and because there's one ID per row there's no need for SUM .

This changes the approach. It first strings the answers together:

concat(q1,q2,q3,q4,q5) -- result for ID=1 in the test data: 'ABCAC'

... then it sucks every occurrence of A from the string:

replace(concat(q1,q2,q3,q4,q5), 'A', '') -- result for ID=1: 'BCC'

... the first string ( ABCAC ) is length 5 , and the second string ( BCC ) is length 3. The difference in length is the number of A answers: 2 . That's about as well as I can explain this. Now for the query:

select
  id,
  5 - length(replace(concat(q1,q2,q3,q4,q5), 'A', '')) AS CountA,
  5 - length(replace(concat(q1,q2,q3,q4,q5), 'B', '')) AS CountB,
  5 - length(replace(concat(q1,q2,q3,q4,q5), 'C', '')) AS CountC
from surveytable;

The updated Fiddle is here .

This gives the raw data only. The formatting will be a bit tricky but it shouldn't be too bad, especially if you do it with a front-end language. If you must use MySQL for this, it will probably be easier to put the above into a subquery and apply the formatting in the outer query:

select
  id,
  CONCAT('You have chosen ' ...and miles of formatting logic using CountA, etc)
from (
  select
    id,
    5 - length(replace(concat(q1,q2,q3,q4,q5), 'A', '')) AS CountA,
    5 - length(replace(concat(q1,q2,q3,q4,q5), 'B', '')) AS CountB,
    5 - length(replace(concat(q1,q2,q3,q4,q5), 'C', '')) AS CountC
  from surveytable) x

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