How to get the latest 5 company data from two tables - php

I have 2 tables in mysql database.
a) company
cid company_name
===================
1 AstraZeneca
2 Emirates
3 Development Bank of Singapore
4 Royal Copenhagen
5 xxx
6 xxx
2) history
hid user_id view_id is_save mark_as view date
==============================================================
1 2 2 0 3 2016-08-25 22:06:12
2 3 3 1 3 2016-08-25 22:07:12
3 3 3 0 1 2016-08-25 22:08:12
4 3 2 0 1 2016-08-25 22:09:12
5 2 4 0 1 2016-08-25 22:10:12
6 4 5 0 1 2016-08-25 22:11:12
7 4 6 0 1 2016-08-25 22:12:12
This view_id is containing cid value.
Now, always I want to show latest 5 company_name from company table as ascending order based on history table view_id.
For that purpose I am doing following query. But company_name is not showing either ASC or DESC order
Here is the query :
$getViewID3 = mysqli_query($link, "SELECT view_id, hid, is_save FROM history WHERE user_id = '$user_id' AND mark_as = 3 GROUP BY view_id ORDER BY view_date DESC LIMIT 5 ");
if(mysqli_num_rows($getViewID3) > 0 ) {
while( $fetchViewId3 = mysqli_fetch_array($getViewID3) ) {
$viewid3 = (int) $fetchViewId3['view_id'];
$hid3 = (int) $fetchViewId3['hid'];
$is_save3 = (int) $fetchViewId3['is_save'];
$getCompany = mysqli_query($link, "SELECT company_name FROM company WHERE cid = '$viewid3' ORDER BY company_name DESC");
if(mysqli_num_rows($getCompany) > 0 ) {
while ($fetchCompany2 = mysqli_fetch_array($getCompany)) {
$cName = htmlspecialchars($fetchCompany2['company_name']);
$url_link = "{$url}company.php?cid=$viewid";
if($is_save3 == 1) {
$checked = 'checked = "checked"';
} else {
$checked = '';
}
echo "<li><a onClick='window.document.location=\"$url_link\"'> $cName </a> <input type='checkbox' class='data_save' $checked data-hid='$hid' data-saveid='$viewid3' name='save_history'></li>";
}
}
}
For example : Result is showing : A, E, D, R, L letter order.
It's should be show : A, D, E, L, R letter Order from company_name column.

If I didn't misunderstand:
SELECT
C.company_name
FROM company C
INNER JOIN
(
SELECT
view_id,
MAX(view_date) max_view_date
FROM history
WHERE is_save IN (0,1) AND mark_as = 3
GROUP BY view_id
ORDER BY max_view_date DESC
LIMIT 5
) AS t
ON C.cid = t.view_id
ORDER BY C.company_name ASC;
Note:
Since you want latest 5 companies the following query will put the last view_date beside the view_id.
Now if you sort these rows based on descending order of max_view_date and later limit the result to 5 then you will get at most five view_ids from the inner query.
Later a simple INNER JOIN between this result set and your company table will finish the job.
Sorry, sorting the final result in ascending order of company name will finish the job.
EDIT:
In order to get all the columns from history table and company_name column from company table:
SELECT
C.company_name,
t.*
FROM company C
INNER JOIN
(
SELECT
history.*
FROM history
INNER JOIN
(
SELECT
view_id,
MAX(view_date) max_view_date
FROM history
WHERE is_save IN (0,1) AND mark_as = 3
GROUP BY view_id
ORDER BY max_view_date DESC
LIMIT 5
) AS latestHistory
ON history.view_id = latestHistory.view_id AND history.view_date = latestHistory.max_view_date
) AS t
ON C.cid = t.view_id
ORDER BY C.company_name ASC;

Related

MYSQL Issue in fetching profit data from multiple table

I have 3 MYSQL Tables User table and 2 Transactions table.
My User table is as follows.
id inviter_id active .... (other columns)
2 1 1
3 1 1
4 2 1
5 1 1
6 2 1
My txn1 table is
id payer_id receiver_id amount type
1 2 1 20 profit
2 3 1 30 profit
3 4 2 20 profit
4 3 2 50 profit
5 5 2 20 profit
My txn2 table is
id payer_id receiver_id amount txn_type
1 2 1 20 profit
2 3 2 30 profit
3 4 2 20 profit
4 3 1 50 profit
5 5 1 20 profit
What I need to get is,
Consider I'm querying for the user 2. I need the profit he has earned from each of his downline or referrals using the inviter_id column.
For example, If I want to get the profit of User #2 from Txn1 and Txn2 table, it should get the txns made by user 4 and user 6 in txn1 and txn2 tables.
What I have tried so far is,
$userID = 2;
$this->db->select('u.id as partner_id, SUM(txn1_profit.amount) AS t1Profit, SUM(txn2_profit.amount) AS t2Profit');
$this->db->from('users u');
$this->db->join('txn1 txn1_profit', "u.id = txn1_profit.payer_id AND $userID = txn1_profit.receiver_id AND 'profit' = txn1_profit.txn_type",'LEFT');
$this->db->join('txn2 txn2_profit', "u.id = txn2_profit.payer_id AND $userID = txn2_profit.receiver_id AND 'profit' = txn2_profit.txn_type",'LEFT');
$this->db->where('u.inviter_id', $userID);
$this->db->group_by('u.id');
$query = $this->db->get();
$row = $query->result();
if (empty($row))
return FALSE;
return $row;
The problem with this query is i'm getting a huge sum value.
If schema of your transaction tables is same then I would suggest you to change your schema and have one single transaction table to store such information. By changing your current design will help you to build simple queries may reduce no. of joins.
For your current schema I can think of 2 possible ways to address your profit value issue.
Calculate sum from your transaction tables in sub-clause and then do a join with users table
select u.inviter_id,
sum(t1.t1Profit),
sum(t2.t2Profit),
sum(t1.t1Profit) + sum(t2.t2Profit) total
from users u
left join (
select payer_id, sum(amount) t1Profit
from tx1
where 2 = receiver_id
and 'profit' = type
group by payer_id
) t1 on u.id = t1.payer_id
left join (
select payer_id, sum(amount) t2Profit
from tx2
where 2 = receiver_id
and 'profit' = txn_type
group by payer_id
) t2 on u.id = t2.payer_id
where u.inviter_id = 2;
Or combine data of your transaction tables using union all and then do a join with users table
select u.inviter_id,
sum(t1.amount) total
from users u
left join (
select payer_id, amount
from tx1
where 2 = receiver_id
and 'profit' = type
union all
select payer_id, amount
from tx2
where 2 = receiver_id
and 'profit' = txn_type
) t1 on u.id = t1.payer_id
where u.inviter_id = 2;
DEMO

how to mysqli inner join with 3 tables

In the end I need results to contain all data from all 3 tables. How to join the 3 tables so all is present in the end. Here is what I have so far:
if ($results = $db->query("SELECT * FROM HWData
LEFT JOIN ClassData
ON HWData.class = ClassData.class
LEFT JOIN Judges
ON Judges.groupnum = ClassData.groupnum
ORDER BY HWData.entrynum",
MYSQLI_USE_RESULT)) {
$result_set = mysqli_fetch_all($results, MYSQLI_ASSOC);
echo json_encode($result_set);
The results are not as expected. It's odd that console.log[i]['groupnum']; shows correct groupnum but $("#output").append("<p>"+data[i]['groupnum']); shows only 1's
3 tables as follows:
ClassData
groupnum abbr
0 DQB
0 DQC
1 SUM
1 PP
1 FOS
1 VANF
1 VANS
2 AFCF
2 AFCS
2 ICCS
2 CCS
3 LSUF
3 LTMS
4 HL
4 MC
Judges
judge group
Coleen 4
Daniel 3
Aaron 2
Jeff 1
HWData
entrynum fname class
1 Esteban FOS
2 Dalia PP
3 Sheri
4 Sheri HL
5 Sheri MC
10 Danita ICCS
11 Chris AFCS
Ok, so i figured out you can use multiple joins.
if ($results = $db->query("SELECT * FROM HWData
LEFT JOIN ClassData
ON HWData.Abbr = ClassData.Abbr
LEFT JOIN Judges
ON Judges.groupnum = ClassData.groupnum",
MYSQLI_USE_RESULT)) {
$result_set = mysqli_fetch_all($results, MYSQLI_ASSOC);
echo json_encode($result_set);
$results->close();
}

Mysql join with latest update in 4 tables

Hi here is my tables..
Table Sites
sid sname uid
---- ---------- ----
1 aaa.com 1
5 bbb.com 1
Table keywords_s
kid skeywoird
---- ----------
1 word1
2 word2
Table matchon
mid uid sid kid
---- ------ ----- -----
1 1 1 1
2 1 1 2
Table rank
mid rank dateon url
---- ------ ------- -----
2 7 08-May-2014 bbb.com/a
2 6 09-May-2014 bbb.com/2
And my query
"SELECT
keywords_s.skeyword,
keywords_s.kid,
sites.sname,
rank.rank,
rank.url,
rank.dateon
FROM matchon
Inner JOIN sites ON sites.sid = matchon.sid
Inner JOIN keywords_s ON keywords_s.kid = matchon.kid
Inner JOIN rank ON rank.mid = matchon.mid
where matchon.uid = :uid and sites.sname = :sname and sites.deactive != '1'
group by keywords_s.skeyword order by rank.rank
"
I am getting output
rank keyword dateon url
---- --------- ------- -----
7 word2 08-May-2014 bbb.com/a
Output needed is
rank keyword dateon url
---- --------- ------- -----
6 word2 09-May-2014 bbb.com/2
Here what i want to get ...
1st Group by keywords_s.skeyword order by rank.rank (this is coming But)
2nd Order by rank.slno desc (not working)
(I need 2nd order to work so i can get latest rank and date with, group by skeyword and order by rank)
SELECT keywords_s.skeywor
, keywords_s.kid
, sites.sname
, rank.rank
, rank.url
, rank.dateon
FROM matchon JOIN sites ON sites.sid = matchon.sid
JOIN keywords_s ON keywords_s.kid = matchon.kid
JOIN rank ON rank.mid = matchon.mid AND
rank.dateon = (SELECT MAX(dateon) FROM rank WHERE mid = matchon.mid)
WHERE matchon.uid = :uid and sites.sname = :sname and sites.deactive != '1'
GROUP BY keywords_s.skeyword order by rank.rank
This should work as per your requirement
"Select * from(SELECT
keywords_s.skeyword,
keywords_s.kid,
sites.sname,
rank.rank,
rank.url,
rank.dateon
FROM matchon
Inner JOIN sites ON sites.sid = matchon.sid
Inner JOIN keywords_s ON keywords_s.kid = matchon.kid
Inner JOIN rank ON rank.mid = matchon.mid
where matchon.uid = :uid and sites.sname = :sname and sites.deactive != '1'
order by rank.rank desc)xyz
group by xyz.skeyword
"

php mysql select lowest value from multiple coloumn

i have database with this condition :
table hotel -----> table hotel price
table hotel :
hotel_id | hotel_name |
1 hotel1
2 hotel2
table hotel price
price_id | hotel_id | room_type | single | Double | extra |
1 1 superior 5 10 20
2 1 deluxe 3 5 10
and i would show start smallest price from hotel1
hotel1 star from "smallest value"
i tried with this but not work
$query = ("SELECT LEAST(COL1,COL2,COL3) FROM rug WHERE COL1 != '' AND COL2!= '' AND COL3 != ''");
$result=mysql_query($query);
if (!$result) {
die('Invalid query: ' . mysql_error());}
$num=mysql_numrows($result);
$i=0;
while ($i < $num)
{
$pricing[$i]=mysql_result($result, $i);
$i++;
}
sort($pricing);
$lowest_price = $pricing[0]; //lowest price
thank raymond for the answer this is almost correct
select
*
, least(single, `double`, extra) as lowest_price
from hotel_price
where
hotel_id = 1
order by
lowest_price
;
with this will show lowest_price column at hotel price table
PRICE_ID HOTEL_ID ROOM_TYPE SINGLE DOUBLE EXTRA HOTEL_NAME LOWEST_PRICE
2 1 deluxe 3 5 10 hotel1 3
1 1 superior 5 10 20 hotel1 5
but i want just show one lowest price from lowest_price column
the smallest is 3
Any thoughts? Thanks!
Not completely sure if you need this..
if you know the id of hotel with name "hotel1" already
select
*
, least(single, `double`, extra) as lowest_price
from hotel_price
where
hotel_id = 1
order by
lowest_price
;
If you don't know the id of the hotel you need to join
select
*
, least(single, `double`, extra) as lowest_price
from
hotel_price
inner join
hotel
on
hotel_price.hotel_id = hotel.hotel_id
where
hotel.hotel_name = 'hotel1'
order by
lowest_price
;
see http://sqlfiddle.com/#!2/f947b/3 for demo note the demo has more queries what should give you the same results
By your SQL syntax I presume you are using MySQL. Than you can solve this by this approach:
SELECT
(SELECT COL1 from rug) as myField
UNION
(SELECT COL2 from rug)
UNION
(SELECT COL3 from rug)
order by myField ASC LIMIT 1

How to limit / offset query that returns several rows per unique ID?

My issue is that I need to paginate data from this query:
function search($search_term, $limit, $offset)
{
$id = $this->auth->get_user_id();
$query = $this->db->query("
SELECT user_id,
first_name,
cars_name,
cars_id
FROM user_profiles
LEFT JOIN cars
ON cars.id_fk = user_id
WHERE user_id NOT LIKE '$id'
AND activated = 1
AND banned = 0
AND first_name LIKE '%$search_term%'
ORDER BY first_name ASC
");
$search_data = array();
foreach ($query->result() as $row) {
$search_data[$row->user_id]['name'] = $row->first_name;
$search_data[$row->user_id]['cars'][$row->cars_id] = array(
'cars_name' => $row->cars_name);
}
return $search_data;
}
A sample data table / query response would be:
1 JOE HONDA 123
1 JOE TOYOTA 124
2 MAC VW 125
2 MAC HONDA 126
2 MAC TESLA 127
3 STU SUBARU 128
3 STU KIA 129
-----------
Page 1
-----------
1 JOE HONDA 123
TOYOTA 124
2 MAC VW 125
HONDA 126
------------
Page 2
------------
3 STU SUBARU 128
KIA 129
If I enter a limit and offset at the end of MySQL query
...
LIMIT $limit
OFFSET $offset;
");
the limit and offset are applied to the total number of rows, not the the number of rows grouped by user.
I've tried using GROUP BY but was unable to make it work.
My goal is to make the query as above but LIMIT and OFFSET the query by a number of rows that counts users, not all rows.
Any ideas?
I don't see a way to do this in one query. My solution would be to get the count of unique ID's using a group by query with the same parameters:
SELECT COUNT(1) AS uid_count
FROM user_profiles
LEFT JOIN cars
ON cars.id_fk = user_id
GROUP BY user_profiles.user_id
WHERE user_id NOT LIKE '$id'
AND activated = 1
AND banned = 0
AND first_name LIKE '%$search_term%'
Then fetch the uid_countmysql_num_rows and use that to calculate pagination variables for the above query.
The solution really is to use a GROUP BY clause:
SELECT SQL_CALC_FOUND_ROWS
user_id,
first_name,
cars_name,
cars_id
FROM user_profiles
LEFT JOIN cars
ON cars.id_fk = user_id
WHERE user_id NOT LIKE '$id'
AND activated = 1
AND banned = 0
AND first_name LIKE '%$search_term%'
GROUP BY user_id
ORDER BY first_name ASC
LIMIT 100
The order is important. GROUP BY first, then ORDER BY, and then OFFSET/LIMIT.
Notice the SQL_CALC_FOUND_ROWS up there? After the query has executed, if you want to get the total row count (including those who aren't returned because of the LIMIT clause), just use:
SELECT FOUND_ROWS() AS `count`
And fetch the count column.
However, like you said, the rows will collapse and you will lose some cars_name and cars_id values.
Another solution is to use GROUP_CONCAT, then split it in PHP:
SELECT
user_id,
first_name,
GROUP_CONCAT(cars_name SEPARATOR ','),
GROUP_CONCAT(cars_id SEPARATOR ','),
FROM user_profiles
LEFT JOIN cars
ON cars.id_fk = user_id
WHERE user_id NOT LIKE '$id'
AND activated = 1
AND banned = 0
AND first_name LIKE '%$search_term%'
ORDER BY first_name ASC
LIMIT 100
This would give you something like:
1 JOE HONDA,TOYOTA 123,124
2 MAC VW,HONDA,TESLA 125,126,127
3 STU SUBARU,KIA 128,129
If you want to get a list like this
Page 1
----------------------
1 JOE HONDA 123
1 JOE TOYOTA 124
Page 2
----------------------
2 MAC VW 125
2 MAC HONDA 126
2 MAC TESLA 127
Page 3
----------------------
3 STU SUBARU 128
3 STU KIA 129
Forget about limit, do this instead:
A - First retrieve a list of user id's and insert that into a temp table
CREATE TEMPORARY TABLE `test`.`temp_user_ids` (
`id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (`id`)
)
ENGINE = MEMORY
B - Next insert the relavant user_id's into the table.
INSERT INTO temp_user_ids
SELECT null, user_id
FROM user_profiles
LEFT JOIN cars
ON cars.id_fk = user_id
WHERE user_id NOT LIKE '$id'
AND activated = 1
AND banned = 0
AND first_name LIKE '%$search_term%'
ORDER BY user_id DESC /*insert in reverse order !*/
The lowest user_id is the last_insert_id in the temptable, and the temp_table
items are in sequential order.
C - Set the SQL #var #current_id to the last_insert_id in the temp_table.
SELECT #current_id:= LAST_INSERT_ID()
D - Next select relevant rows from the table, using only the user_id you want.
SELECT count(*) as row_count,
up.user_id,
first_name,
group_concat(cars_name) as car_names,
group_concat(cars_id) as car_ids,
FROM user_profiles up
LEFT JOIN cars
ON cars.id_fk = up.user_id
INNER JOIN temp_user_ids t
ON (t.user_id = up.user_id)
WHERE t.id = #current_id
GROUP BY up.user_id
ORDER BY cars.id
E - Now lower the #current_id
SELECT #current_id:= #current_id - 1;
F - And repeat step D and E until there's no more rows to be had.
The first field row_count tells you the number of rows aggregated in the fields
car_names and car_ids. You can separate these fields by using php's explode.

Categories