0

Hello from Bulgaria, it is my very first post here so excuse me if I do not explain everything very well.

I'm doing admin panel in website(PHP, MYSQL) for Online Language Courses. I have to see:

  1. A list with all the users registered in the website
  2. If they are paid or not paid one of the courses ( they are 4 courses at the momment )
  3. IF they are already input a Promo Code for any of the courses.

The table names and important table column's names are:

  1. USERS: user_id, email, real_name
  2. PAID_COURSES: paid_course_id, paid_course_name
  3. USER_PAID_XREF: xref_id, user_id, paid_course_id
  4. VOUCHERS: voucher_id, user_id, voucher, paid_course_id

I think the final result must be an array looks like:

    array(2)
    { 
    [1]=> array(5) { 
    ["user_id"]=> string(1) "1", 
    ["email"]=> string(15) "email@email.com", 
    ["real_name"]=> string(5) "ANJEL" ,
    ["paid_course_id"]=> array(4) {
    [1]=> string(1) "1" 
    [2]=> string(1) "0" 
    [3]=> string(1) "1" 
    [4]=> string(1) "0"
    },
    ["voucher"]=> array(4) {
    [1]=> string(20) "VOUCHER-11111111111"
    [2]=> string(1) "0"
    [3]=> string(19) "VOUCHER-AAAAAAAAAAA"
    [4]=> string(1) "0"
    }
     }
    [2]=> array(5) { 
    ["user_id"]=> string(1) "2" 
    ["email"]=> string(16) "office@email.com" 
    ["real_name"]=> string(5) "MITKO" 
    ["paid_course_id"]=> array(4) {
    [1]=> string(1) "0" 
    [2]=> string(1) "1" 
    [3]=> string(1) "1" 
    [4]=> string(1) "0"
    },
   ["voucher"]=> array(4) {
    [1]=> string(1) "0"
    [2]=> string(20) "VOUCHER-22222222222"
    [3]=> string(19) "VOUCHER-BBBBBBBBBBB"
    [4]=> string(1) "0"
    }
     }

     }
  1. [1]=> is the key for user_id
  2. In the array have 2 additional arrays with length of the number of the paid courses at all (Example at the momment have only 4 paid courses - English, spanish... etc)
  3. ["paid_course_id"][1]=> the key [1] here is the paid_course_id from paid_courses table
  4. ["paid_course_id"][2]=> string(1) "1" - The value "1" here is: If there is a row in the table user_paid_xref for the current paid_course_id (in the example paid_course_id=2) is with value 1 if there is not a row then the value is 0 ( With other words the user has paid this course or the user is not paid this course)
  5. ["voucher"][3]=> string(19) "VOUCHER-BBBBBBBBBBB" - Same here as paid_course_id for a key of the array element.
  6. ["voucher"][3]=> string(19) "VOUCHER-BBBBBBBBBBB" - The Value here is from table VOUCHERS column's name - voucher

So that's it I hope that someone will understand it. Thanks in advance

  • Are you asking for someone to write the query for you? Because thats not what this site is for! – RiggsFolly Aug 16 '13 at 21:45
  • Welcome to SO. However, we discourage asking for codes. You can post at least what have you tried so far. – Mark Aug 17 '13 at 04:53

2 Answers2

0

You can use the left join in order to get the multiple vouchers and multiple courses

SELECT * FROM `USERS` u
LEFT JOIN `VOUCHERS` v ON (u.user_id = v.user_id)
LEFT JOIN `USER_PAID_XREF` upx ON (u.user_id = upx.user_id)
LEFT JOIN `PAID_COURSES` pc ON (upx.paid_course_id = pc.paid_course_id)
M Khalid Junaid
  • 63,861
  • 10
  • 90
  • 118
  • 1
    This will produce a full cross-product of all the vouchers and courses. The tricks is to combine that all into the two sub-arrays he wants. – Barmar Aug 16 '13 at 22:00
  • Thank you for the quick answer, but I want each User to be in a 1 row, because I should be able to activate him with a link: Imagine:1 row in the table in the HTML EMAIL, NAME, ACTIVATE FOR ENGLISH, ACTIVATE FOR FRENCH, IS PAID SPANISH(AND THERE IS NO LINK), ACTIVATE FOR RUSSIAN – Анжел Миленов Aug 16 '13 at 22:01
  • @Barmar then he has run the two queries foreach user to get the vouchers and the courses i can provide the answer with `GROUP_CONCAT` by grouping the courses an vouchers in the single row but `GROUP_CONCAT` has the limit of string and first he has to increase that – M Khalid Junaid Aug 16 '13 at 22:11
0
SELECT u.user_id, u.email, u.real_name,
       GROUP_CONCAT(CONCAT(upx.paid_course_id IS NOT NULL, '|' IFNULL(v.voucher, '0'))) course_vouchers
FROM `USERS` u
LEFT JOIN `USER_PAID_XREF` upx ON (u.user_id = upx.user_id)
LEFT JOIN `VOUCHERS` v ON (u.user_id = v.user_id AND upx.paid_course_id = v.paid_course_id)
GROUP BY u.user_id

This will produce one row for each user, with comma-separated lists in course_vouchers. The elements of this list are pipe-separated course_id flag and voucher.

I left PAID_COURSES out of the query because your results don't seem to use anything from that table.

The PHP will be something like:

$result = array();
while ($row = $stmt->fetch_assoc()) {
    // Split apart the pieces of $row['course_vouchers']
    $courses = array_map(function($x) { return explode('|', $x); },
                         explode(',', $row['course_vouchers']));
    $row['paid_course_id'] = array_map(function($x) { return $x[0]; }, $courses);
    $row['voucher'] = array_map(function($x) { return $x[1]; }, $courses);
    unset($row['course_vouchers']);
    $result[] = $row;
}

Note that the default limit on the size of GROUP_CONCAT is 1024 characters. For data like yours, that looks like about 40 courses if they have vouchers for all of them. If a user may have more courses, you may need to increase this limit. See this question for how to do this.

Community
  • 1
  • 1
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • What about the character limit http://stackoverflow.com/questions/5445048/is-there-a-length-limit-to-group-concat-or-another-reason-why-it-would-not-work ?? – M Khalid Junaid Aug 16 '13 at 22:22
  • @dianuj For short strings like this, that's not likely to be an issue. – Barmar Aug 16 '13 at 22:24