Grab most recent values from table using php and mysql - php

Im having the below sql table structure and im trying to grab values from 2 tables using codeigniter.
table: salesman
id sales_name ref_id
1 kevin 174
2 mike 574
3 nick 777
table: sales_report
id salesman_id product purchased_date dispatched
1 2 BF0214 04-November-2011 Yes
2 2 CF0474 09-November-2011 No
3 2 BF0111 10-November-2011 No
4 3 BF0714 15-November-2011 Yes
5 3 BF0435 15-November-2011 Yes
6 2 BF0335 18-November-2011 Yes
7 1 BF0714 22-November-2011 Yes
8 1 BF0335 25-November-2011 Yes
im passing the salesman_id to the model to grab and display the values in my view.
my html table is as below
Ref ID | Salesman Name | Last product Sold | Sold Date | Dispatched Status
the problem that im having how can query to get the sales_name and ref_id from the salesman table and get the most recent product name, dispatched and purchase_date from from the sales_report table?
eg:
Ref ID | Salesman Name | Last product Sold | Sold Date | Dispatched Status
174 kevin BF0335 25-November-2011 Yes
574 mike BF0335 18-November-2011 Yes
777 nick BF0435 15-November-2011 Yes

Use
GROUP BY
ORDER BY
for getting this done

You need to use SELECT values from the sales_report, LEFT JOIN salesman to get in the sales_name and ref_id, ORDER BY the purchased_date (DESC to get the most recent one first instead of the oldest first), and GROUP BY the salesman.id to get it to only return one row per salesman.
SELECT * FROM sales_report LEFT JOIN salesman ON sales_report.salesman_id = salesman.id ORDER BY purchased_date DESC GROUP BY salesman.id

You should find last product by two criteras: its sold date and by its id; because some products may be sold in one day. So, try this one -
SELECT s.ref_id, s.sales_name, sr.product, sr.purchased_date, sr.dispatched FROM salesman s
JOIN (
SELECT salesman_id, product, purchased_date, dispatched FROM (
SELECT salesman_id, product, purchased_date, dispatched, IF(#salesman_id = salesman_id, #i := #i + 1, #i := 1) n, #salesman_id := salesman_id
FROM sales_report, (SELECT #i:= 0, #salesman_id = NULL) vars
ORDER BY salesman_id ASC, purchased_date DESC, id DESC) t
WHERE t.n = 1
) sr
ON s.id = sr.salesman_id;

Related

Sum 3 Tables and Subtract the User Request

Hello Developers/Programmers
I am working on withdrawal function on my website.
So it goes like this
I need to total the 3 tables i have by User ID with status of '1' ,and Subtract the Inputed amount by the User Requested the Withdrawal
These are my 3 tables
tbl_bonus_1
id | amount | user_id | status
1 20 1 1
2 20 1 1
3 20 3 1
tbl_bonus_2
id | amount | user_id | status
1 30 1 1
2 30 1 1
3 30 3 1
tbl_bonus_3
id | amount | user_id | status
1 40 1 1
2 40 1 1
3 40 3 1
Now I need to get all that 3 tables by USER ID and get the total of it.
After getting the total i need to subtract the Inputted quantity of the USER
and update the status to 0 so that the user cant withdraw again.
Im using Codeigniter 3.1.5
select user_id, sum(amount)
from
(select * from tbl_bonus_1
union
select * from tbl_bonus_2
union
select * from tbl_bonus_3) tt
where status = 1
group by user_id
DEMO:
http://sqlfiddle.com/#!9/7f1807e/1
And UPDATE (single user):
UPDATE tbl_bonus_1 t1 INNER JOIN tbl_bonus_2 t2
ON t1.user_id = t2.user_id
INNER JOIN tbl_bonus_3 t3
ON t1.user_id = t3.user_id
SET t1.amount = 0, t2.amount = 0, t3.amount = 0
WHERE t1.user_id = 1;
Realistically, you don't want to subtract from these tables if you want to manage a balance. You need to add a 4th table that is withdrawal amount, so you can capture the transactions. If you have a total of 160 across 3 tables, and the user withdrawals 150, how would you determine which to decrement.
I would suggest actually consolidating all of these into 1 trasaction table, and capture the amounts there.
So to get what you need you will need to leverage variables which will need to be passed to the query. Below will give you what you are asking for. That being said, this is not the correct way to do this. Also, there is no way to determine which of the 3 balances you want to subtract the withdraw from. This is just not how transaction ledgers work and for a lot of reasons I am not going to get in to right now. At the bottom of this answer is how I suggest you should build your table. You will be able to get information with more easy while capturing more/better data.
How to get data from current structure:
set #withdraw = 150.00, #user = 1;
select user_id, sum(amount) as prevBalance
, #remainingBalance := if(#user = user_id,sum(amount)-#withdraw,sum(amount)) as remainingBalance
from
(select * from tbl_bonus_1
union
select * from tbl_bonus_2
union
select * from tbl_bonus_3) balance
group by user_id;
How you should build your schema:
CREATE TABLE ledger (id int NOT NULL AUTO_INCREMENT
,user_id int
, amount decimal(5,2)
, transaction_type varchar(20)
,PRIMARY KEY (ID));
INSERT INTO ledger VALUES
(null,1,20,'Bonus1'),
(null,1,20,'Bonus1'),
(null,3,20,'Bonus1'),
(null,1,30,'Bonus2'),
(null,1,30,'Bonus2'),
(null,3,30,'Bonus2'),
(null,1,40,'Bonus3'),
(null,1,40,'Bonus3'),
(null,3,40,'Bonus3'),
(null,1,-150,'Withdraw')
;
Then all you would need to do is run the following query.
select user_id, sum(amount) balance from ledger
group by user_id;

how to retrieve the type of value which is there more number of times in a column in a table and count of it?

s.no Name type of vehicle allotted
1 ram bus
2 krish car
3 raj bus
4 albert car
5 johnson bike
6 raghu car
consider this is a table now i want to retrieve the type of vehicle which is there more number of times in the table and count of it. is there any particular method(query).
You have to use COUNT and GROUP BY.
Count will give you the number of rows grouped by type field.
SELECT COUNT(id) as count, type FROM table_name GROUP BY type
The output should be like this:
count | type
2 | bus
3 | car
1 | Bike
If you need just the highest one, append to the query:
ORDER BY count DESC LIMIT 1
I think you have to count and select the top 1 row.
Query
SELECT t.* FROM(
SELECT `type`, COUNT(`type`) `count`
FROM `your_table_name`
GROUP BY `type`
)t
ORDER BY `count` DESC LIMIT 1;

Select rows from a table and use multiple interrelated columns for ordering

I have a table that contains information about "teams". Teams can have subteams - which has been implemented by each row having a "parent_id" column that contains the "team_id" of that subteam's parent. Here's an example of the data:
team_id team_name parent_id
1 sales (null)
2 executives (null)
3 emea sales 1
4 apac sales 1
5 uk sales 3
What I'm trying to achieve is simply to select all rows in the table in order of team_id, BUT I want subteams returned right after their parent team, also in team_id order. So, for the above example data, I would want the data returned in this order:
team_id team_name parent_id
1 sales (null)
3 emea sales 1
5 uk sales 3
4 apac sales 1
2 executives (null)
I've spent several hours wondering how to achieve this, and really haven't come up with anything useful! I would appreciate any pointers on how to approach this.
Note, I am working with an existing project and can't really make drastic database/implementation changes. I'm using PHP and Oracle with the use of stored procedures, which are new to me.
You can use a hierarchical query with the ORDER SIBLINGS BY clause, like so:
WITH teams AS (SELECT 1 team_id, 'sales' team_name, NULL parent_id FROM dual UNION ALL
SELECT 2 team_id, 'executives' team_name, NULL parent_id FROM dual UNION ALL
SELECT 3 team_id, 'emea sales' team_name, 1 parent_id FROM dual UNION ALL
SELECT 4 team_id, 'apac sales' team_name, 1 parent_id FROM dual UNION ALL
SELECT 5 team_id, 'uk sales' team_name, 3 parent_id FROM dual)
SELECT team_id,
team_name,
parent_id
FROM teams
CONNECT BY PRIOR team_id = parent_id
START WITH parent_id IS NULL
ORDER SIBLINGS BY team_id;
TEAM_ID TEAM_NAME PARENT_ID
---------- ---------- ----------
1 sales
3 emea sales 1
5 uk sales 3
4 apac sales 1
2 executives

Getting a daily summary of figures from shop database

I have the following tables, in a standard shop:
(id is always primary key, auto-increment, ts is always type TIMESTAMP, updated ON_UPDATE CURRENT_TIMESTAMP)
table sales:
id | total | tendered | flag | userID | ts
1 0.6 0.6 0 4 2013-11-21 08:12:23
Sales is the parent table, userID is related to the user that made the sale. total and tendered are both of type FLOAT. flag is of type VARCHAR and could be Free Order.
table receipts:
id | oID | pID | quantity | ts
1 1 26 1 2013-11-21 08:11:25
Receipts holds a line for each unique type of product sold. oID is type INT and relates to the id of table sales. pID is of type INT and relates to the id of table products.
table products:
id | name | price | cID | display | ts
1 Mars 0.6 3 1 2014-01-17 07:55:25
Products is the central data for each product in the database. Here is a line for mars bars. cID relates to the id in table categories.
table categories
id | name | display | ts
3 Snacks 1 2013-11-14 12:06:44
Categories is the table holding all the data about each category, and can have multiple products relating to a single row. display is of type INT and dictates when the category is enabled or disabled (1 = 'true')
My question is, I want to output information like this:
**Snacks**
(name) (quantity) (price) (total)
Fruit 3 50p £1.50
Twix 1 60p 60p
Boost 1 60 60p
**Hot Drinks**
(name) (quantity) (price) (total)
English Tea 15 60p £9.00
Speciality Teas 2 60p £1.20
Which I have the following SQL for:
SELECT categories.name AS category, products.name, pID,
(SELECT SUM(quantity) FROM receipts WHERE pID=r.pID AND DATE(ts) = CURDATE()) AS quantity,
products.price,r.ts
FROM receipts r
LEFT JOIN products ON r.pID = products.id
LEFT JOIN categories ON products.cID = categories.id
WHERE DATE(r.ts) = CURDATE()
GROUP BY r.pID
ORDER BY categories.name;
Which seems to give me the correct information, but I am not 100% certain. If anyone could verify that this works, I would be most grateful. But when I want to see a particular day, I get unusual figures with the following SQL:
$postfrom = $_POST['from_mm']."/".$_POST['from_dd']."/20".$_POST['from_yy'];
$postto = $_POST['to_mm']."/".$_POST['to_dd']."/20".$_POST['to_yy'];
$from = strtotime($postfrom . " 6:00");
$to = strtotime($postto . " 23:59");
$itemised = select("SELECT categories.name AS category, products.name, pID,
(SELECT SUM(quantity) FROM receipts WHERE pID = r.pID AND UNIX_TIMESTAMP(r.ts) > '{$from}' AND UNIX_TIMESTAMP(r.ts) < '{$to}')
AS quantity, products.price
FROM receipts r
LEFT JOIN products ON r.pID = products.id
LEFT JOIN categories ON products.cID = categories.id
WHERE UNIX_TIMESTAMP(r.ts) > '{$from}'
AND UNIX_TIMESTAMP(r.ts) < '{$to}'
GROUP BY r.pID
ORDER BY categories.name;");
(function 'select' simply returns an array of the SQL table). The thing is, I could find the results easily by looping through in PHP and adding it up that way. But I know this is possible with SQL, I just don't know why It isnt working. Can somebody please help?
Edit SQL sample fiddle is here: http://sqlfiddle.com/#!2/23af4 although I couldn't do more than half a day of data due to 8000 character restrictions.
Try this:
SELECT categories.name AS category, products.name AS name,
receipts.quantity AS quantity, products.price AS price,
(receipts.quantity * products.price) AS total
FROM categories
JOIN products
ON categories.id = products.cID
JOIN receipts
ON receipts.pID = products.ID
WHERE DATE(receipts.ts) = CURDATE()
ORDER BY categories.name
SQLFiddle demo
With regard to the date restriction, you could use BETWEEN ... AND ... to specify the date and time. Using an absolute date and time moment or relative to the current day and time, for example WHERE DATE(receipts.ts) BETWEEN concat(curdate() -5,' 6:00:00 AM') AND curdate() -4

MySql : Order by and Group By combining not giving the latest record

Using the following query I am looking for a solution to get the latest record that having some conditions.
But it gives me the first record, not the latest. I think its only considering the group by
Please advise me
SELECT * FROM `contacts` WHERE `id_receiver`=1 GROUP BY `id_thread` ORDER BY created DESC
id id_sender id_thread sender_email id_receiver created(datetime)
1 2 2 51 1 2012-03-24 13:44:48
2 4 4 1 5 2012-04-26 13:46:05
3 2 2 51 1 2012-04-09 12:12:30
Required output
id id_sender id_thread sender_email id_receiver created(datetime)
3 2 2 51 1 2012-04-09 12:12:30
I had done a test just swap the order by and group by , giving me an erros.
Anybody can just look in to this?. Thanks.
EDIT Edited question, forget to write id_thread
How can you GROUP BY id_thread when there is no id_thread column in your table?
SELECT *
FROM contacts
WHERE id_receiver = 1
--- GROUP BY id_thread
--- removed
ORDER BY created DESC
LIMIT 1 --- only show one row
Based on your comments, what you want is the latest (ordered by created) row for every id_thread, which is a different and more complex query. There's even a tag for this kind of queries, named [greatest-n-per-group].
SELECT c.*
FROM contacts AS c
JOIN
( SELECT id_thread, MAX(created) AS created
FROM contacts
WHERE id_receiver = 1
GROUP BY id_thread
) AS g
ON (g.id_thread, g.created) = (c.id_thread, c.created)
WHERE c.id_receiver = 1
if records goes sequential than you might SORT by id too -- if and only if it's created in sequential order --

Categories