I'm having this PDO query to call data from a MySQL.
$sql = "SELECT itemName FROM furniture WHERE itemID = :item";
While calling for this particular itemName, is it possible to get the next and previous itemNames by using its itemID within this same query itself without having to write a new query to get the next and previous itemNames?
e.g.
if
itemID | itemName
___________________________
553 | Mahogani Black Chair
554 | Teak Round Table
555 | Thulang Relaxing Chair
556 | Teak Relaxing Chair
$sql = "SELECT itemName FROM furniture WHERE itemID = :item";
$stmt = $connect->prepare($sql);
$stmt->execute(array(':item'=>"554"));
$rslt = $stmt->fetchAll(PDO::FETCH_ASSOC);
I'm looking away of getting Teak Round Table and Mahogani Black Chair and Thulang Relaxing Chair
Please use this code:
(SELECT itemName FROM furniture WHERE itemID < 554 order by itemID desc limit 1)
UNION
(SELECT itemName FROM furniture WHERE itemID >= 554 order by itemID asc limit 2)
For Example code :
MyTable:
================
id Store_name
================
1 English
2 French
3 Tamil
4 Uk
5 US
<?php
$con = mysqli_connect("localhost","root","ramki","ramki");
$sql = "(SELECT store_name FROM store WHERE id < 2 order by id desc limit 1)
UNION
(SELECT store_name FROM store WHERE id >= 2 order by id asc limit 2)";
$query = mysqli_query($con,$sql);
while ($row = mysqli_fetch_assoc($query)) {
echo $row['store_name'];
echo "<br>";
}
?>
$sql = "SELECT itemName FROM furniture WHERE itemID IN (:item-1, :item, :item+1) ORDER BY itemID";
For iterating the results, you can also use PDO fetch() function to get each row.
Related
i'm attempting to list my suppliers in order, with showing the items that I need to order under the supplier. But the script originally provided to me lists the supplier each time.
This is what i've got:
$dataSQL = "SELECT * FROM inventory WHERE product_active='Y' ORDER BY product_supplier, product_category, product_code ASC";
$data = mysql_query($dataSQL) or die(mysql_error());
$rows = mysql_num_rows($data);
while($result = mysql_fetch_array( $data )) {
$category=$result['product_category'];
$id=$result['id'];
$item1=$result['product_name'];
$code1=$result['product_code'];
$code2=$result['product_suppliercode'];
$soh=$result['product_soh'];
$reorder=$result['product_reorder'];
$supplier=$result['product_supplier'];
$order=$result['product_reorder']-$result['product_soh'];
// output row from database
if($soh<$reorder) {
echo "
<tr><td>$supplier</td><td>SOH $soh | Order $order</td></tr>
<tr><td>$item1</td><td>$code1</td></tr>
";
}
}
However, if there is more than 1 product low on stock from 1 supplier, i only want to list the supplier once, not every time.
This is the current result:
Low & Out of Stock Report
Biz Supplies SOH 3 | Order 1
White Thermal Travel Mug 0000000001030
Office Works SOH 14 | Order 1
Frixion Stamp Coffee Cup (Orange) 4902505508073
Office Works SOH 0 | Order 1
Frixion Stamp Apple 4902505508103
PHE (Paper Handling Equipment) SOH | Order 1
20mm 100pk Plastic Binding Comb
(box)
0000000004115
(sorry, not sure how to display here in table format). The end result would be that it would show the supplier name once, then on the next row show the item, code, soh & reorder
You can select DISTINCT product_supplier.
So your query will become:
SELECT DISTINCT ON product_supplier *
FROM inventory
WHERE product_active='Y'
ORDER BY product_supplier, product_category, product_code ASC
Alternatively, you can use a GROUP BY on the column that you want to eliminate duplicates:
SELECT *
FROM inventory
WHERE product_active='Y'
GROYP BY product_supplier
ORDER BY product_supplier, product_category, product_code ASC
I am trying to show statistics for goals scored by players, however sometimes the same player is added to the database with the same playerID, when a player is added twice how can I add the values together to show it as a total, rather than echo the player twice.
db structure example:
playerID | Goals | Season | leagueID
1 5 1 1
2 1 1 1
1 2 1 2
5 3 1 1
1 3 2 2
2 2 2 1
php:
$query = $db->query('SELECT * FROM playerstats ORDER BY goals DESC LIMIT 30');
$num = $query->num_rows;
if($num > 0) {
foreach($query as $row) {
$playerID = $row['playerID'];
$goals = $row['goals'];
echo '
<tr>
<td>'.$playerID.'</td>
<td>'.$goals.'</td>
</tr>
';
}
}
This would show playerID 1, 3 seperate times.
How can I make it show playerID 1 just once with all the goals added together (10)
I have tried changing the query to: SELECT DISTINCT * FROM playerstats ORDER BY goals DESC LIMIT 30 but this made no difference.
Group BY will help you:
<?php
$query = $db->query('SELECT SUM(p.goals) as total_goals,
p.playerID, p.leagueID, p.Season
FROM playerstats as p
GROUP BY p.playerID, p.leagueID, p.Season
ORDER BY total_goals DESC LIMIT 30');
$num = $query->num_rows;
if($num > 0) {
foreach($query as $row) {
echo '
<tr>
<td>'.$row['playerID'].'</td>
<td>'.$row['total_goals'].'</td>
</tr>
';
}
}
Please note, that my query will group also by season and leagues, if you want total goals throughs seasons and leagues, your group by will be:
GROUP BY p.playerID
If you want only the playerID and the sum of the goals not mattering the Season or the leagueID, change your query to:
SELECT DISTINCT playerID AS player,
(SELECT SUM(goals) FROM playerstats WHERE playerID = player) AS totalGoals
FROM playerstats
Well you would group results in array then loop over it. Or sort at SQL level.
Something like this might work:
$playerStats = array();
foreach($query as $row)
{
if(array_key_exists($row['playerID'], $playerStats))
$playerStats[$row['playerID']] += $row['goals'];
else
$playerStats[$row['playerID']] = $row['goals'];
}
// Then loop over playerStats
foreach($playerStats as $playerID => $playerGoals)
}
echo $playerID;
echo $playerGoals;
{
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
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.
$query1 = "select *
from linkat_link
where emailuser = '$email2'
or linkname ='$domain_name2'
ORDER BY date desc
LIMIT $From,$PageNO";
id catid discription price
------------------------------------
1 1 domain name 100
2 1 book 50
3 2 hosting 20
4 2 myservice 20
in this script i have one problem , if i have an ID for Each Cantegory , i have some duplicated CATID which has different content but shares the same CATID, i need to make any duplicated CATID to show in one , and all the discription will be in the same line (Cell) on the same row .
So Each CatID will have all the details in one Row without any redundancy in the CATID
Using:
SELECT t.catid,
GROUP_CONCAT(t.description),
GROUP_CONCAT(t.price)
FROM LINKAT_LINK t
WHERE t.emailuser = mysql_real_escape_string($email2)
OR t.linkname = mysql_real_escape_string($domain_name2)
GROUP BY t.catid
ORDER BY t.date DESC
LIMIT mysql_real_escape_string($From), mysql_real_escape_string($PageNO)
...will return:
catid description price
--------------------------------
1 domain name,book 100,50
2 hosting,myservice 20,20
See the documentation for what the GROUP_CONCAT function does.
How to print it to screen using PHP?
Use:
<?php
$query1 = "SELECT t.catid,
GROUP_CONCAT(t.description) AS grp_desc,
GROUP_CONCAT(t.price) AS grp_price
FROM LINKAT_LINK t
WHERE t.emailuser = mysql_real_escape_string($email2)
OR t.linkname = mysql_real_escape_string($domain_name2)
GROUP BY t.catid
ORDER BY t.date DESC
LIMIT mysql_real_escape_string($From), mysql_real_escape_string($PageNO)";
$result = mysql_query($query1);
while($row = mysql_fetch_array($result)) {
echo "CatID:{$row['catid']} <br>" .
"Description : {$row['grp_desc']} <br>" .
"Price : {$row['grp_price']} <br><br>";
} ?>