7

I have a table lead_submission which contains value of a user in a specific format like

agent_name     qa_details
xxx      1001:|1083:|504:Yes|1009:|
ccc      504:Yes|1083:No|1008:|1009:|

now I want to get the count of only say 504:Yes from two rows

these values are coming from another table paid_response

qno    paid_response
504     Yes
1083    No
1083    Possibly

<?php
//db connection goes here

$sql=mysql_query("select qno,paid_response from paid_response where qno='504' ");
while($rows=mysql_fetch_array($sql)) {    
$exqnos= $rows['qno'].'|'.$rows['paid_response'];
}

list($key,$val)=explode('|',$exqnos);
$exqno[$key]=$val;

foreach($exqno as $qno=>$value) {
$string .="qa_details LIKE '%|$qno:$value|%' ";  
}

$sql=mysql_query("SELECT count(agent_name) as agent_cnt,count($string) as ppicount FROM `lead_submission` WHERE $string "); ?>

               <table border="1">
                <thead>
                  <tr>
                    <th>CountAgent</th>
                    <th>504-COUNT</th>                      
                  </tr>

<?php
while($row=mysql_fetch_array($sql)) { ?>

     <tr style="color:red" >            
        <td><?php echo $row['agent_cnt']; ?></td>
        <td><?php echo $row['ppicount']; ?></td>            
        </tr>

<?php
}
?> 

Now by doing this i am getting count as 2 for 504:Yes

CountAgent  504-COUNT
 2            2        //as u can see that `504:Yes` has occured two times in lead_submission table.

my point is how can i also count another combination say 1083:No and show count in the same table

NB:- cant we just fetch the combination like `504:Yes` or `1083:No` or `1083:Yes` from paid_response table to maintain stability so that i dont have to change the query everytime. 

CountAgent  504-COUNT   1083-Count
  2           2           1        //how to get this count `1083:No` . as u can see it only appeared 1 times in `lead_submission` table
Cœur
  • 37,241
  • 25
  • 195
  • 267
black
  • 729
  • 5
  • 13
  • 28
  • 7
    Why are you storing the data like this? This would be WAY easier if you'd normalize the information properly, and it's probably a better idea to fix that over implementing it this way. – Erik Dec 24 '14 at 08:59
  • can you take an example ? – OnlyMAJ Dec 24 '14 at 09:00
  • 'without this complications.' The complications come from the fact that you did't choose a good format to save your data. You'd rather normalize your data. – Lorenz Meyer Dec 24 '14 at 09:01
  • so u mean there is no way out that i can count from here? – black Dec 24 '14 at 09:04
  • It is not a good idea to remove the | and : . How could you distinguish from the question 504 and the answer 504? – Lorenz Meyer Dec 24 '14 at 09:05
  • Btw, it is not clear what you want to count : occurrences of question numbers ? Answers that are ' Yes '? Please clarify. – Lorenz Meyer Dec 24 '14 at 09:07
  • no i only want to count number of 504 and 1083 from each row and then show in with 504 and 1083. please see i have edited my quesion – black Dec 24 '14 at 09:08
  • Yes. Step 1: See normalization – Strawberry Dec 24 '14 at 09:21
  • As others have said, read up on the First Normal Form - you shouldn't be storing data like this in a SQL database. – William Orazi Dec 26 '14 at 08:08
  • (i) You want to count either one of "1083:No" and "1083:Yes" - but have a heading of "1083-Count" for the single hit for "1083:No". Do you really want identical (looking) column headings? (ii) Are you ever going to query the sum for any, e.g., "1008:" (Either not, yet, qualified with any of "Yes", "No" - or even despite this being the case?) In other words: Could "paid_response" ever be `NULL`? And if so, what exactly should happen if so? (iii) Is it safe to assume, all values to be entered in "paid_response" will -concatenated verbatim- be fully valid (table) column names in any respect? – Abecee Jan 01 '15 at 19:56
  • see 1st paid_response would not be null. 2nd in any case count any matching combination fetching from previous table 103:No or 1083:Possibly. in a single row both combination cant be present only 1083:Yes or 1083:Possibly – black Jan 01 '15 at 20:48

7 Answers7

5

Try this:

SELECT COUNT(DISTINCT ls.agent_name), 
       SUM(CASE WHEN pr.qno = 504 AND pr.paid_response = 'Yes' THEN 1 ELSE 0 END) AS '504-Count', 
       SUM(CASE WHEN pr.qno = 1083 AND pr.paid_response = 'No' THEN 1 ELSE 0 END) AS '1083-Count'
FROM lead_submission ls 
INNER JOIN paid_response pr
ON CONCAT('|', ls.qa_details, '|') LIKE CONCAT('%|', pr.qno, ':', pr.paid_response , '|%');

Check the SQL FIDDLE DEMO

OUTPUT

| COUNTAGENT | 504-COUNT | 1083-COUNT |
|------------|-----------|------------|
|          2 |         2 |          1 |

::EDIT::

First execute below query

SELECT GROUP_CONCAT('SUM(CASE WHEN pr.qno = ', qno, ' AND pr.paid_response = ''', paid_response,''' THEN 1 ELSE 0 END) AS ''', qno, '-Count''') 
FROM paid_response;

Use output of this query and build your final query as below:

query = 'SELECT COUNT(DISTINCT ls.agent_name), ' + outputOfAboveQuery + ' FROM lead_submission ls NNER JOIN paid_response pr ON CONCAT('''|''', ls.qa_details, '''|''') LIKE CONCAT('''%|''', pr.qno, ''':''', pr.paid_response , '''|%''');';

Execute this string in your code so you can get dynamic query to fetch the counts

Saharsh Shah
  • 28,687
  • 8
  • 48
  • 83
  • 1
    While an answer like this may work for this specific case (and variations thereof) this is not the recommended path. The absolute BEST solution is to normalize the database first. Google for "Database Normal Form". Kudos for @Saharsh for finding a solution anyway. – STT LCU Dec 29 '14 at 13:11
  • but if the combination like `1083:No` changes to `1083:Yes` in `paid_response` table then i have to change this query to Yes. cant we just fetch the combination from `paid_response` table to maintain stability – black Dec 29 '14 at 13:18
  • @black If you want to perform something like that and then fetch the records from paid_response thable then build a query in your code with dynamically creation `SUM(CASE WHEN pr.qno = 504 AND pr.paid_response = 'Yes' THEN 1 ELSE 0 END) AS '504-Count', ` this portion and in this you have to replace `504` to `your fetched qno column data` and `Yes` to 'your fetched paid_response column data`. So you can create dynamic query for that – Saharsh Shah Dec 29 '14 at 13:21
  • @shah i didnt got ur code. if i paste ur edited 1st query its echoing the query in table header in phpmyadmin. can u plz elaborate ur code and comment.thnx for the response and quick solution. all i want to fetch the combination from paid_response table. – black Dec 29 '14 at 18:14
  • @black I have shown a part of code rest code of PHP you have to write. First you have to call my first query in PHP method and store the output of that query in one variable and build the second query using that above variable and execute that query in PHP you will get the desired output. – Saharsh Shah Dec 30 '14 at 05:45
  • @black My First query fetch all combination of paid_respone and create a string, to create a dynamic query to get desired result – Saharsh Shah Dec 30 '14 at 05:47
  • @SaharshShah i have tried ur code. i took a variable say $string .=ur first query then passed $string into ur 2nd query, where in the first i passed $key in pr.qno and $val in pr.paid_response that is coming from foreach($explode as $key=>$val){ but still no success. when i am fetching with while loop its throwing parse error 'unexpected while(T_WHILE)' – black Dec 30 '14 at 09:14
  • @black You do not have to pass anything in my first query that fields are fetched from table so remove that keys and pass column name to fetch the data – Saharsh Shah Dec 30 '14 at 09:16
  • sorry man its the same thing i am getting, either i am not able to understand or i am doingsomething wrong. ok firstly in ur 1st query i removed passing of $key $value and keep it the same way, stored that into a variable $xxx . and passing it in ur 2nd query. my question is how the desired qno and paid_response of the combination is checking. i couldnt crack it out. thnx for ur response – black Dec 30 '14 at 09:28
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/67898/discussion-between-saharsh-shah-and-black). – Saharsh Shah Dec 30 '14 at 09:31
3
<?php
$con = mysql_connect('localhost', 'root', '');
mysql_select_db('test',$con);

function countIt($checkArray)
{
    $checkVals = explode(',', $checkArray); 
    foreach($checkVals AS $val){
        list($qNo, $pRes) = explode(':', $val);
        $query = mysql_query("SELECT * FROM `paid_response` WHERE `qno`='$qNo' AND `paid_response`='$pRes'");
        if(mysql_num_rows($query) > 0){
            $query = mysql_query("SELECT * FROM `lead_submission` WHERE `qa_details` LIKE '%$val%'");
            $countArray[$val] = mysql_num_rows($query);
        } else {
            $countArray[$val] = 0;
        }
    }

    foreach($countArray AS $key=>$val){
        echo $key . '  =>  ' . $val . "<br/>";
    }
}

echo countIt('504:yes,1083:no,1083:yes,1083:possibly,504:no');

Try this Man!

Minivetsystem
  • 301
  • 1
  • 2
2

Echoing the comments of others. You should probably normalize your model.

That said, it is not impossible to extract the result you require, just that the solution will be inefficient, not scalable, difficult for new developers to understand and not very extendable.

Also, it is easier to extract the data in the long format rather than the wide format, i.e.

# wide data format
CountAgent  504-COUNT   1083-Count
  2           2           1  

vs.

# Long data format
dimension   count
CountAgent    2
504-Count     2
1083-Count    1

The transformation from long to wide is easier in php (and may not even be required).

SELECT 
CONCAT(pr.qno, ":", pr.paid_response) dimension,
COUNT(*) `count`
FROM lead_submission ls 
JOIN paid_response pr 
  ON ls.qa_details LIKE CONCAT("%", pr.qno, ":", pr.paid_response, "%")
-- insert where clause 
GROUP BY 1
UNION
SELECT 'count-agent' dimension,
COUNT(DISTINCT ls.agent_id) `count`
FROM lead_submission ls 
JOIN paid_response pr 
  ON ls.qa_details LIKE CONCAT("%", pr.qno, ":", pr.paid_response, "%")
-- insert where clause        
GROUP BY 1

In the query above, the where clause should be the same for both the united selects, and I think for your case it should take the following form:

WHERE CONCAT(pr.qno, ":", pr.paid_response) IN (<key-value pair 1>, <key-value pair 2>, ...)

This returns the following result:

DIMENSION       COUNT
1083:No         1
504:Yes         2
count-agent     2

Here's the sqlfiddle demo

Haleemur Ali
  • 26,718
  • 5
  • 61
  • 85
1

Assuming the format of the data stays the same, you could try something like this (untested):

$query[] = "SELECT COUNT(agent_name) as agent_cnt"; // number of agents in total

// Counts of each question/answer.
foreach ($exqno as $qno => $value) {
    $query[] = "(SELECT COUNT(agent_name) FROM lead_submission WHERE qa_details LIKE '%|$qno:$value|%') AS count_{$qno}";  
}

$full_query = implode(', ', $query) . " FROM lead_submission";

$sql = mysql_query( $full_query );
PZL
  • 51
  • 5
1
SELECT productOwner_org_id, 
(SELECT COUNT(*) FROM tblProducts P2 WHERE P1.product_id=p2.product_id AND productDescription='Leisure at PER01 IVR Gas') AS '504-data',
(SELECT COUNT(*) FROM tblProducts P3 WHERE P1.product_id=p3.product_id AND productDescription='Leisure Plus at Centerpoint') AS '1083-data'
FROM tblProducts p1
WHERE productOwner_org_id = 'AEG01'
AND
(SELECT COUNT(*) FROM tblProducts P2 WHERE P1.product_id=p2.product_id AND productDescription='Leisure at PER01 IVR Gas') != 0
OR
(SELECT COUNT(*) FROM tblProducts P3 WHERE P1.product_id=p3.product_id AND productDescription='Leisure Plus at Centerpoint') != 0


;

As you can see it's kind of ugly.

A) Your better option is to reorganize your data or B) When presenting/format your data differently with more php logic

terary
  • 940
  • 13
  • 30
1

Count agent can be different in each search case. If in the above example you search for '504','1083:No' then it is not 2 in both cases. I suggest you modify your script like this:

<?php
$array = array('504','1083');
//db connection goes here
$th="";
$tr="";
foreach($array as $arr) {
$srch=$arr;
$sql=mysql_query("select qno,paid_response from paid_response where qno=$srch ");
while($rows=mysql_fetch_array($sql)) {    
$exqnos= $rows['qno'].'|'.$rows['paid_response'];
}

list($key,$val)=explode('|',$exqnos);
$exqno[$key]=$val;

foreach($exqno as $qno=>$value) {
$string .="qa_details LIKE '%|$qno:$value|%' ";  
}
$sql=mysql_query("SELECT count(agent_name) as agent_cnt,count($string) as ppicount FROM `lead_submission` WHERE $string ");
        $th.="<th>CountAgent(".$arr.")</th><th>(".$arr.")-COUNT</th>";                      
while($row=mysql_fetch_array($sql)) {         
        $tr.="<td>".$row['agent_cnt']."</td><td>".$row['ppicount']."</td>";           
}
}
?> 
   <table border="1">
     <thead>
     <tr>
     <?php echo $th; ?>                     
     </tr>
     </thead>
     <tbody>
     <tr style="color:red" >            
     <?php echo $tr; ?>             
     </tr>
     </tbody>
     </table>
  • This way you could insert your search variables in the array in the beginning. –  Dec 31 '14 at 06:35
  • ty for the response but ur code is not working `Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given` and the table heading is showing only the 2nd array value like u have given 504,1083 in array so its showing as 1083 not 504. – black Dec 31 '14 at 07:15
  • its working fine with only one value passed like 504 or 1083 in the array. but not when both – black Dec 31 '14 at 07:19
  • so its not counting accurate count(agent_name), its displaying count(agent_name) as its displaying count($string).means if 1083:No is 1 agent count is 1. if 1083:No is 0 agent count is showing 0 – black Dec 31 '14 at 09:41
  • try now please corrected and without mysql_real_escape_string –  Dec 31 '14 at 10:06
  • The way you count agent_name i think is wrong, you have to have multiple agent name counts per qa_details if your qa_details = 504 your agent count is 2 if qa_details = 1083:No your agent count is 1, I only tell this since your 'qa_details' is coming from 'qno:paid_response' so paid_response (Yes,No,...) is part of the input. –  Dec 31 '14 at 10:15
  • Ok leaving the agent count but actually its not counting the 2nd parameter 1083 or any other number 663 that is present only counting 504 or the 1st parameter in the array – black Dec 31 '14 at 10:29
  • Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given – black Dec 31 '14 at 10:54
  • @black: Where is the "any other number 663" in your comment comming from? Don't find it anywhere on this page (in its current state). – Abecee Jan 01 '15 at 19:54
  • see i am fetching those from another table so 504 1083 and next could be 663 – black Jan 01 '15 at 20:45
-1

Okay, here is incomplete answer. Incomplete as I don't bother to write specific query for you. But I am writing on how to do it.

Note: Read about normalization. You will see your mistake.

If you can modify you data by adding | at start of it, i.e. make 1001:|1083:|504:Yes|1009:| as |1001:|1083:|504:Yes|1009:| will help you a lot.

Now, you can easily search a TEXT Search on %|<ID>:% this ensure that you find either 504 or 1009 or whatever number by replacing <ID> with that number.

Did you read normalization yet? Anyways.

once you did this you can now do Row to Column concept (I think it is know as PIVOT Queries, google it while you google normalization. ). Some of examples are given here

MySQL Row to Column Or Mysql query to dynamically convert rows to columns

Sorry for incomplete answer but Text Search is your kind a best bet, and better create a View of it before you use it in complex queries. But really it will be VERY SLOW To fetch data and is not recommended.

Hope you find normalization yet...if not try this: https://www.google.co.in/#q=normalization+in+database

Oh and don't forget to index that column ...

Community
  • 1
  • 1
Sumit Gupta
  • 2,152
  • 4
  • 29
  • 46