MySQL Statement to joins 2 tables and sum same items qty - php

I have 2 tables, customer and transaction.
Customer:
--------------------------------------------
ID | Name | Tel
--------------------------------------------
1 | Peter | 123 4567
2 | John | 456 1234
3 | Alice | 789 4561
4 | Amy | 741 8525
Transaction:
--------------------------------------------
CustID | Books | Pens | Ruler
--------------------------------------------
1 | 2 | 0 | 1
2 | 1 | 0 | 0
1 | 0 | 3 | 0
1 | 0 | 0 | 1
2 | 1 | 1 | 1
3 | 0 | 2 | 2
I need the following
Results:
-------------------------------------------------------------------
ID | Name | Tel | Books | Pens | Ruler
-------------------------------------------------------------------
1 | Peter | 123 4567 | 2 | 3 | 2
2 | John | 456 1234 | 2 | 1 | 1
3 | Alice | 789 4561 | 0 | 2 | 2
4 | Amy | 741 8525 | 0 | 0 | 0
Basically it will sum the Books, Pens and Ruler of the same Customer.
I've tried:
$sql = "select
`customer`.id,
`custmaster`.name,
`custmaster`.tel,
`transaction`.id,
`transaction`.books,
`transaction`.pens,
`transaction`.ruler,
from `customer`
left join `transaction`
on `customer`.id=`transaction`.custid
ORDER BY `customer`.id ASC";
But display none. :( I do understand that I needed the sum() function somewhere. Anybody can help?

Use SUM and GROUP BY.
SELECT c.id, c.name, c.tel, SUM(t.books) as books, SUM(t.pens) AS pens, SUM(t.ruler) AS ruler
FROM customer AS c
LEFT JOIN transactions AS t ON c.id = t.custid
GROUP BY c.id
ORDER BY c.id

Try this way
select
`customer`.id,
`custmaster`.name,
`custmaster`.tel,
`transaction`.id,
sum(`transaction`.books) as books,
sum(`transaction`.pens) as pens,
sum(`transaction`.ruler) as ruler,
from `customer`
left join `transaction`
on `customer`.id=`transaction`.custid
Group by `customer`.id,`customer`.Name
ORDER BY `customer`.id ASC";

Related

MySQL pivot to make a row into a colum

I have three tables, products, customers, order
Product:
id | name |
1 | milk |
2 | bread|
3 | Pea |
Customer:
id | name | category
1 | James | retailer
2 | Paul | vendor
3 | Dave | retailer
Order:
id | product_id | customer_id | qty | price
1 | 1 | 2 | 23 | 50
2 | 2 | 2 | 4 | 30
3 | 3 | 2 | 6 | 10
4 | 2 | 1 | 9 | 30
5 | 3 | 1 | 2 | 10
6 | 1 | 3 | 6 | 50
7 | 3 | 3 | 7 | 10
When i do a query to show transactions by customers with category of vendor like
SELECT customer.name, product.name as pname, order.qty, order.price FROM customer, product, order
WHERE customer.id = order.customer_id
AND product.id = order.product_id AND customer.category = "vendor"
i will get something like:
name | pname | qty | price
Paul | milk | 23 | 50
Paul | bread | 4 | 30
Paul | pea | 6 | 10
I want this instead:
name | milk | bread | pea | total
Paul | 23 | 4 | 6 | 90
While that of retailers will look like this:
SELECT customer.name, product.name as pname, order.qty, order.price FROM
customer, product, order
WHERE customer.id = order.customer_id
AND product.id = order.product_id AND customer.category = "retailer"
I will get a table like this:
name | pname | qty | price
James | bread | 9 | 30
James | pea | 2 | 10
Dave | milk | 6 | 50
Dave | pea | 7 | 10
But i want this instead:
name | milk | bread | pea | total
James | 0 | 9 | 2 | 40
Dave | 6 | 0 | 7 | 60
Simply use conditional aggregation for pivoting columns. And be sure to use explicit joins instead of the deprecated implicit join as former has been the standard for 25 years in ANSI-92.
SELECT c.name,
SUM(CASE WHEN p.name = 'milk' THEN o.qty ELSE 0 END) as milk,
SUM(CASE WHEN p.name = 'bread' THEN o.qty ELSE 0 END) as bread,
SUM(CASE WHEN p.name = 'pea' THEN o.qty ELSE 0 END) as pea,
SUM(o.price) AS Total
FROM `customer` c
INNER JOIN `order` o
ON c.id = o.customer_id
INNER JOIN `product` p
ON p.id = o.product_id
WHERE c.category = 'vendor' -- same for retailer
GROUP BY c.name
I think that you cannot have this response structure directly from one simple select
name | milk | bread | pea | total
James | 0 | 9 | 2 | 40
Dave | 6 | 0 | 7 | 60
because your database is getting one row foreach retailers/customer order.
I know that using a server language like PHP or Java you will can handle the data and retrive like you want.

How to group or marge SQL rows via PHP after query

I have a MySQL table like bellow
id | roll | exam_id | course_id | marks | status
----------------------------------------------------------
1 | 01001 | 1 | 1 | 56 | 1
2 | 01002 | 1 | 1 | 68 | 1
3 | 01003 | 1 | 1 | 55 | 1
4 | 01004 | 1 | 1 | 67 | 1
5 | 01001 | 1 | 2 | 54 | 1
6 | 01002 | 1 | 2 | 59 | 1
7 | 01003 | 1 | 2 | 62 | 1
8 | 01004 | 1 | 2 | 63 | 1
9 | 01001 | 2 | 3 | 61 | 1
10 | 01002 | 2 | 3 | 48 | 1
11 | 01003 | 2 | 3 | 22 | 1
12 | 01004 | 2 | 3 | 39 | 1
Now I want to have all the row with exam_id = 1
SELECT * FROM result WHERE exam_id=1 ORDER BY course_id
After that I need to display this table inside HTML after grouping it by roll means one row for each roll that have row-span according to the course number of the result table
Roll | course_id | marks
-----------------------------
01001 | 1 | 56
| 2 | 68
-----------------------------
01002 | 1 | 55
| 2 | 67
-----------------------------
01003 | 1 | 55
| 2 | 62
-----------------------------
01004 | 1 | 67
| 2 | 63
I'm using Codeigniter framework to doing this project. Any suggestions about how I can I do this?
Thank you in advance.
[EDIT]
Current SQL I'm using to do this:
SELECT * FROM `exam_result` JOIN `course` ON `course`.`course_tab_id`=`exam_result`.`result_course` WHERE `exam_id` = '1' AND `result_status` = 1 GROUP BY `exam_result`.`exam_roll`, `course`.`course_tab_id` ORDER BY `exam_result`.`exam_roll` ASC, `course`.`course_id` ASC
Try this but the difference in this table on my first query is that the course title will be included on a single table, I have set the marks as AVG due to so if ever you have duplicate data you will see their average result for the course and roll of a school or whatever you use this structure for
SELECT roll, exam_id, a.course_id, marks, status, course_title, course_credit
FROM
(SELECT roll, exam_id, course_id, AVE(marks) as marks, status FROM result) as a
LEFT JOIN
(SELECT course_id, course_title, course_credit FROM course) as b
ON
a.course_id = b.course_id
WHERE exam_id = '1' -- you can remove this if you wanted all exam appear on your list
GROUP BY roll, exam_id, a.course_id, marks, status, course_title, course_credit
ORDER BY roll, course_id, marks
Try this sql query
SELECT Roll, course_id, AVG(marks)
FROM result WHERE exam='1'
GROUP BY Roll, course_id
ORDER BY roll, course_id, marks

agent sales report, sums all their sales and minimized display result by total sales

i have 3 table user, products and sales
user
UID | NAME
1 | agent1
2 | agent2
3 | agent3
4 | agent4
5 | agent5
products
PID | PNAME
1 | P1
2 | P2
3 | P3
sales
SID | UID | PID | SALES_CREATED
1 | 3 | 1 | 2013-07-13 01:15:04
2 | 1 | 1 | 2013-07-13 01:25:34
3 | 3 | 1 | 2013-07-13 02:01:34
4 | 3 | 1 | 2013-07-13 02:45:34
5 | 5 | 1 | 2013-07-13 02:56:34
6 | 5 | 1 | 2013-07-13 03:21:34
7 | 2 | 3 | 2013-07-13 03:38:34
8 | 3 | 2 | 2013-07-13 03:51:34
9 | 4 | 2 | 2013-07-13 04:25:34
10 | 3 | 1 | 2013-07-13 04:45:04
11 | 1 | 3 | 2013-07-13 04:55:34
12 | 2 | 2 | 2013-07-13 05:01:34
13 | 1 | 3 | 2013-07-13 05:15:34
14 | 5 | 3 | 2013-07-13 05:36:34
15 | 5 | 3 | 2013-07-13 06:21:34
where the results of sales per agent is: (sort by user UID)
user | P1 | P2 | P3 |
agent1 | 1 | 0 | 2 |
agent2 | 0 | 1 | 1 |
agent3 | 4 | 1 | 0 |
agent4 | 0 | 1 | 0 |
agent5 | 2 | 0 | 2 |
now, i want a result to sort user that has a greatest sale by P1 and a minimum of 3 result only, and the result will be like this
user | P1 | P2 | P3 |
agent3 | 4 | 1 | 0 |
agent5 | 2 | 0 | 2 |
agent1 | 1 | 0 | 2 |
can you guys give me a best mysql_query to show that result?
Oh, something like this...
SELECT uid
, SUM(pid=1) p1
, SUM(pid=2) p2
, SUM(pid=3) p3
FROM sales
GROUP
BY uid
ORDER
BY p1 DESC
, p2 DESC
, p3 DESC;
+-----+------+------+------+
| uid | p1 | p2 | p3 |
+-----+------+------+------+
| 3 | 4 | 1 | 0 |
| 5 | 2 | 0 | 2 |
| 1 | 1 | 0 | 2 |
| 2 | 0 | 1 | 1 |
| 4 | 0 | 1 | 0 |
+-----+------+------+------+
If handling the display logic at the application level, then your query can be simplified to something more scalable, like this...
SELECT uid
, pid
, COUNT(*)
FROM sales
GROUP
BY uid,pid;
I am only answering because (1) I am bored, and (2) I wanted a brain teaser exercise. I typically do not like to answer when people post and run (don't respond to anyone's comments/posts), or provide what they have tried (no query).
If you want better/more help on SO in the future, it would be beneficial to post the query that you have tried, and when using complex/diverse data like this to create a sqlfiddle - http://sqlfiddle.com/
So with that caveat, here is how you can get your desired results
SELECT
user.NAME as user,
SUM(PID=1) as P1,
SUM(PID=2) P2,
SUM(PID=3) P3
FROM
sales
LEFT JOIN
user
ON
user.UID = sales.UID
GROUP BY
sales.UID
HAVING
P1+P2+P3 >= 3
ORDER BY
P1 DESC, P2 DESC, P3 DESC;
and here is the sqlfiddle example that shows it in action - http://sqlfiddle.com/#!2/d3405/8

Selecting random triplicates (or more) from database

I have two tables:
Students Student_Grades
V------------------------V
+----+------+ +----+------------+---------+-------+
| id | name | | id | student_id | subject | grade |
+----+------+ +----+------------+---------+-------+
| 0 | Dave | | 0 | 0 | Math | 100 |
+----+------+ +----+------------+---------+-------+
| 1 | John | | 1 | 0 | Chem | 90 |
+----+------+ +----+------------+---------+-------+
| 2 | Kate | | 2 | 0 | CompSCI | 95 |
+----+------+ +----+------------+---------+-------+
| 3 | Mimi | | 3 | 1 | ELA | 98 |
+----+------+ +----+------------+---------+-------+
| 4 | 2 | Biology | 92 |
+----+------------+---------+-------+
| 5 | 2 | Chem | 94 |
+----+------------+---------+-------+
| 6 | 2 | Math | 98 |
+----+------------+---------+-------+
| 7 | 3 | Math | 100 |
+----+------------+---------+-------+
I would like to select all subjects and grades from a random student that is enrolled in more than three subjects. (Either Dave or Kate)
Students John and Mimi would not be even considered because they are not enrolled in three subjects.
I know I can achieve this with PHP but I would like this to be done with one query to the database.
SELECT * FROM Students t JOIN (SELECT CEIL(MAX(ID)*RAND()) AS ID FROM Students) AS x ON t.ID >= x.ID LIMIT 1
With the above query, I have selected a random student, with that I can go in and check if they have three subjects with SELECT count(subjects) FROM Students WHERE id=random_id.
If the count returned is below three, then I throw away the results and run the first query again.
How would I attempt this in one query?
This is tested and working:
SELECT *
FROM Students s
JOIN (
SELECT student_id
FROM Student_Grades
GROUP BY student_id
HAVING COUNT(*) >= 3
ORDER BY RAND()
LIMIT 1
) rs
ON rs.student_id = s.id
JOIN
Student_Grades sg
ON sg.student_id = s.id
Here's the SQL Fiddle: http://sqlfiddle.com/#!2/e5b5b/1

MySQL join - ordering results via another table PHP

I have 2 MySQL tables, one of which has a numeric column to orgainise the order I need the items to be displayed:
item_names
menu_id | dish_id | section_id | item_name
--------------------------------------------------
1 | 23 | 2 | Pie
1 | 24 | 2 | Fish
1 | 25 | 3 | Apples
1 | 26 | 2 | Onions
1 | 27 | 2 | Chips
link_extras
extra_id | dish_id | sort
-----------------------------
1 | 23 | 2
2 | 23 | 2
3 | 23 | 2
1 | 24 | 0
5 | 24 | 0
6 | 26 | 3
12 | 26 | 3
1 | 27 | 1
1 | 25 | 0
Basically what I am trying to do is extract each dish with a certain menu_id and section_id from the table item_names and order the output in respect to the sort column in the link_extras table.
so far:
$query="SELECT a.item_name, a.dish_id, b.sort
FROM item_names AS a, link_extras AS b
WHERE a.menu_id='1'
AND a.section_id='2'
AND b.dish_id=a.dish_id
GROUP BY b.dish_id
ORDER BY b.sort";
I am quite new to databases so would appreciate any help. The result I am after is
Fish
Chips
Pie
Onions
Unfortunately just can't get the order correct.
You need to use a simple JOIN
SELECT a.item_name, a.dish_id, b.sort
FROM item_names AS a
JOIN link_extras AS b
ON a.dish_id = b.dish_id
WHERE menu_id = 1
AND section_id = 2
GROUP BY b.dish_id
ORDER BY b.sort
Output:
| ITEM_NAME | DISH_ID | SORT |
------------------------------
| Fish | 24 | 0 |
| Chips | 27 | 1 |
| Pie | 23 | 2 |
| Onions | 26 | 3 |
See this SQLFiddle
SELECT
in.item_name
FROM item_names AS in
LEFT JOIN link_extras AS le
ON le.dish_id = in.dish_id
WHERE in.menu_id = 1
AND in.section_id = 2
ORDER BY le.sort
Demo Here
Output
| ITEM_NAME |
-------------
| Fish |
| Chips |
| Pie |
| Onions |

Categories