tags:

views:

68

answers:

3

Hi, there

I have different queries fetching from different tables in one single page. i want to cut down the database tripping.

here is my code..

$query = "SELECT COUNT(*) as cnt_news FROM news";
$result = mysql_query($query);
$row = mysql_fetch_array($result);


$query = "SELECT COUNT(*) as cnt_adv FROM advertisements";
$result = mysql_query($query);
$row = mysql_fetch_array($result);

$query = "SELECT COUNT(*) as cnt_comm FROM comments";
$result = mysql_query($query);
$row = mysql_fetch_array($result);


$query = "SELECT SUM(CASE WHEN c.approve = '1' AND c.spam = '0' THEN 1 ELSE 0 END) AS cnt_approved,
          SUM(CASE WHEN c.approve = '0' AND c.spam = '0' THEN 1 ELSE 0 END) AS cnt_unapproved,
          SUM(CASE WHEN c.spam = '1' THEN 1 ELSE 0 END) AS cnt_spam
          FROM COMMENTS c";
$result = mysql_query($query);
$row = mysql_fetch_array($result);


$query = "SELECT SUM(a.amount) as t_amnt,
          SUM(a.cashpaid) as t_cpaid,
          SUM(a.balance) as t_bal
          FROM advertisements a";
$result = mysql_query($query);
$row = mysql_fetch_array($result);

i am confused on how to make the query to select the values from three different tables, news, advertisement and comments. how do i cut my code and database trips?

thank you.

+1  A: 

You don't have to cut your database trips, but you can cut your code by using a function

To make a general purpose function would be a way better.

<?php
$num_news = dbgetvar("SELECT COUNT(*) FROM news");
$num_adv  = dbgetvar("SELECT COUNT(*) FROM advertisements");
$num_comm = dbgetvar("SELECT COUNT(*) FROM comments");

function dbgetvar($query){
  $res = mysql_query($query);
  if (!$res) {
    trigger_error("dbget: ".mysql_error()." in ".$query);
    return FALSE;
  }
  $row = mysql_fetch_row($res);
  if (!$row) return NULL;
  return $row[0];
}

always make a function from repetitive code.

Col. Shrapnel
how useful will it be if i use a function, ? is it not bad to make frequent database trips? although i will be using all the values from the query everytime on the page, and the value will not be NULL at any given part of time.
Ibrahim Azhar Armar
@Ibrahim functions are ALWAYS useful to cut down a code. And no, it is not bad to make frequent database trips. It is as if you ask "is it bad to frequently ride a car?" Databases are intended for retrieving data. Nothing bad in such a trips.
Col. Shrapnel
@Col. it is past three hours since i took your advice seriously and begin researching on it, i got to admit it, i am getting used to it, and also i am finding it very very easy to maintain my codes. you made me save my time and headache.. thank you for that :)
Ibrahim Azhar Armar
@Ibrahim I am glad you took my advice. Aside from this particular case, such a function is one of the most necessary tools a developer should have at hand. All these mysql_* are mess, while getting certain info using just one operator (which also does necessary error handling/reporting) is very big help. You can use a similar function to get multiple rows into nested array as well. You will need this array anyway if you gonna use a template of some sort.
Col. Shrapnel
and, needless to say, that it's queries *quality*, not *quantity* should be concern. As long your queries runs fast, any reasonable number is all right. After all it's just a local network daemon call, the same we use for memcache for example. There is nothing bad in such a call itself.
Col. Shrapnel
that is the word of wisdom, how true to say the quality matters a lot not the quantity. and i changed your function quite a bit to match mine requirement needless to say i am getting my result with just three queries in an array. that is so awesome.
Ibrahim Azhar Armar
+1  A: 
$query = "SELECT
COUNT(n.*) as cnt_news,
COUNT(a.*) as cnt_adv,
COUNT(c.*) as cnt_comm,
SUM(CASE WHEN c.approve = '1' AND c.spam = '0' THEN 1 ELSE 0 END) AS cnt_approved,
    SUM(CASE WHEN c.approve = '0' AND c.spam = '0' THEN 1 ELSE 0 END) AS cnt_unapproved,
    SUM(CASE WHEN c.spam = '1' THEN 1 ELSE 0 END) AS cnt_spam,
SUM(a.amount) as t_amnt,
    SUM(a.cashpaid) as t_cpaid,
    SUM(a.balance) as t_bal
FROM
news n, advertisements a, comments c";

That should do it in a single query.

Gazler
so nice, now i see how useful an alias can be, gonna try this out :)
Ibrahim Azhar Armar
@Ibrahim you will understand how awful is this, when you will have to read this code again some time after. Putting different code snippets into one massive solid block is called *obfuscation* and makes it hard to read. While code *readability* is very important thing. Code shouldn't be shortened at any cost. But I understand that you can't see it without certain experience. It's all right, you will learn it eventually :)
Col. Shrapnel
@Col. i am getting confused to which method i should adopt, well atleast you understood. thank you for your suggestion i really appreciate it. and if this is the case then i am considering to change my decision, i am sure you have the better piece of advice for me.
Ibrahim Azhar Armar
@Ibrahim Everything I have I've already told you. How to make a good program out of a confusing mess. As you can see, I don't expect you to change your decision immediately. It's matter of one's own experience. I can't help it. Just try to read this code after couple months. But at least you should use a custom db access function to get this query results anyway.
Col. Shrapnel
Also, this method created `JOIN` of 3 tables unnecessarily which will put the MySQL under unnecessary load and will slow down the queries definitely. If the tables grow large, the query will really become slow as a turtle.
shamittomar
+1  A: 

You can turn to using mysqli library instead of mysql library to connect to MySQL. The use mysqli::multi_query to run multiple queries at once and get results.

Almost all mysql_ functions are available as mysqli_ functions:

<?php
$link = mysqli_connect("localhost", "user", "password", "dbname");

/* check connection */
if (mysqli_connect_errno())
{
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit();
}

//these are your queries. Put them all in a string separated by semicolon ;
$query  = "SELECT COUNT(*) as cnt_news FROM news;";
$query .= "SELECT COUNT(*) as cnt_adv FROM advertisements;";
$query .= "SELECT COUNT(*) as cnt_comm FROM comments;";

// Now execute multi query
if (mysqli_multi_query($link, $query))
{
    do {
        /* store first result set */
        if ($result = mysqli_store_result($link))
        {
            while ($row = mysqli_fetch_row($result))
            {
                printf("%s\n", $row[0]);
            }
            mysqli_free_result($result);
        }
        /* print divider */
        if (mysqli_more_results($link)) {
            printf("-----------------\n");
        }
    } while (mysqli_next_result($link));
}

/* close connection */
mysqli_close($link);
?>

I have shown example for your three queries only. You can put more queries in $query. This way there will be single request to MySQL.

shamittomar
the code looks awesome shamit, but for this project i dont want to use mysqli, i will surely consider using it for the next project. thank you for that code. :)
Ibrahim Azhar Armar