this is my table
row | car_id | car_model | car_features |
1 1 CAR 1 Features 1
2 2 CAR 2 Features 2
3 2 CAR 2 Features 3
and i want to make it like
row | car_id | car_model | car_features |
1 1 CAR 1 Features 1
2 2 CAR 2 Features 2, Features 3
and this is my php mysql script:
<?php
$con = mysql_connect("localhost", "root", "root");
mysql_select_db("car", $con);
$format = mysql_query("SELECT c.* , p.*, d.*,f.* ,e.* FROM bsi_car_master c,bsi_car_type p, bsi_car_vendor d, bsi_selected_features f, bsi_car_features e WHERE c.car_type_id=p.id AND c.car_vendor_id=d.id AND c.car_id = f.car_id AND f.features_id = e.id");
$row = 1;
while($srow = mysql_fetch_array($format))
{
blah blah blah....
}
?>
Use GROUP_CONCAT with GROUP BY. Try this -
SELECT `row`, `car_id`, `car_model`, GROUP_CONCAT(`car_features`, ',')
FROM your_table GROUP BY `car_id`
SELECT car_id,car_model,GROUP_CONCAT(car_features,',')
FROM yourtable
GROUP BY car_id,car_model;
$format = mysql_query("SELECT c.* , p.*, d.*,f.* ,e.*,group_concat(`c.car_features`,',') as `carfeatures` FROM bsi_car_master c,bsi_car_type p, bsi_car_vendor d, bsi_selected_features f, bsi_car_features e WHERE c.car_type_id=p.id AND c.car_vendor_id=d.id AND c.car_id = f.car_id AND f.features_id = e.id group by c.car_id");
Hopefully, it's fairly obvious that I'm no PHP coder, but here's another way to do it, without GROUP_CONCAT()...
<?php
/*
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,car_id INT NOT NULL
,car_model VARCHAR(12) NOT NULL
,car_features VARCHAR(20) NOT NULL
);
INSERT INTO my_table VALUES
(1 ,1 ,'CAR 1','Features 1'),
(2 ,2 ,'CAR 2','Features 2'),
(3 ,2 ,'CAR 2','Features 3');
*/
require('path/to/mysqli/connection/stateme.nts');
$query = "
SELECT id
, car_id
, car_model
, car_features
FROM my_table
ORDER
BY car_model;
";
$result = mysqli_query($db,$query);
$car_id = 0;
while($row = mysqli_fetch_assoc($result)){
if ($car_id== $row['car_id']){
echo " >".$row['car_features']."<br>\n";
} else {
echo $row['car_model']."<br>\n >".$row['car_features']."<br>\n";
$car_id = $row['car_id'];
}
} // end of while loop
/*
Outputs...
CAR 1
>Features 1
CAR 2
>Features 2
>Features 3
*/
?>
Related
I'm trying to condense data that I have in my database into rows with their points tallied to see the most popular.
If I had a data table like:
`data`
item1 item2
1
1 2
1 3
1 3
2 3
And wanted the condensed version to be:
`data_sum`
item1 item2 Tally
1 2 2
1 3 3
2 3 1
How would I achieve this? I have somewhat of an idea here:
$popdata = mysql_query("SELECT * FROM data");
while($add = #mysql_fetch_array($popdata)){
$qitem1 = "SELECT * FROM data_sum WHERE item1='".$add['item1']."'";
$ritem1 = mysql_query($qitem1);
if(mysql_num_rows($ritem1) > 0){
$qitem2 = "SELECT * FROM data_sum WHERE item2='".$add['item2']."'";
$ritem2 = mysql_query($qitem2);
if (mysql_num_rows($ritem2) > 0){
$sql = "UPDATE Tally=Tally + 1 WHERE item1='".$add['item1']."' AND item2='".$add['item2']."'";
$update = mysql_query($sql);
}
else{
$sql = "INSERT INTO data_sum (item1, item2) VALUES('$item1', '$item2')";
$insert = mysql_query($sql);
}
else{
$sql = "INSERT INTO data_sum (item1, item2) VALUES('$item1', '$item2')";
$insert = mysql_query($sql);
}
Yes, I know the total tallies are one more than the rows in the first table. I want the rows with a null column to count towards both tallies with a common factor. This file is going to go through thousands of rows so I want utmost efficiency! Thanks!
All you would need to do is create a new table and then combine an INSERT statement with a GROUP BY'd SELECT statement. This would COUNT() the number of times item1 and item2 were the same and store them in the new tally'd table.
Something along the lines of:
INSERT INTO new_tally_table (item1, item2, Tally)
SELECT item1, item2, COUNT(*)
FROM table
GROUP BY item1, item2
Edit:
Actually re-read the last bit of your question. Think what you want is something like this:
SELECT item1, item2, COUNT(*)
FROM (
SELECT i1.item1, i2.item2
FROM table1 as i1
INNER JOIN (
SELECT DISTINCT item1, item2
FROM table1 WHERE item2 IS NOT NULL
) as i2 ON (i1.item1 = i2.item1)
WHERE i1.item2 IS NULL
UNION ALL
SELECT item1, item2
FROM table1
WHERE item2 IS NOT NULL
) as t
GROUP BY item1, item2
There's probably a better way of writing that though.
There may be a simpler solution, but I can't think of it...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,item1 INT NULL
,item2 INT NULL
);
INSERT INTO my_table (item1,item2) VALUES
(1 ,NULL),
(1 ,2),
(1 ,3),
(1 ,3),
(2 ,3);
SELECT x.item1
, x.item2
, COUNT(DISTINCT y.id)
FROM my_table x
JOIN my_table y
ON y.item1 = x.item1
AND (y.item2 = x.item2 OR y.item2 IS NULL)
AND y.id <= x.id
JOIN
( SELECT item1
, item2
, MAX(id) max_id
FROM my_table
GROUP
BY item1
, item2
) z
ON z.item1 = x.item1
AND z.item2 = x.item2
AND z.max_id = x.id
WHERE x.item2 <> 0
GROUP
BY x.id;
+-------+-------+----------------------+
| item1 | item2 | COUNT(DISTINCT y.id) |
+-------+-------+----------------------+
| 1 | 2 | 2 |
| 1 | 3 | 3 |
| 2 | 3 | 1 |
+-------+-------+----------------------+
This is how my table looks like:
id | name | value
-----------------
1 | user1| 1
2 | user2| 1
3 | user3| 3
4 | user4| 8
5 | user5| 6
6 | user7| 4
7 | user8| 9
8 | user9| 2
What I want to do is to select all the other users, in one query, who's value is user1's value lower than it's value plus 3, higher than it's value minus 3 or equal to it's value.
Something like this:
$result = mysqli_query($con,"SELECT * FROM users WHERE value<'4' OR value>'-2'") or die("Error: ".mysqli_error($con));
while($row = mysqli_fetch_array($result))
{
echo $row['name'].'<br/>';
}
The problem is that users1's value can vary every time the query is run.
Sorry for lame names, but this should work:
NOTE: I named table with your data as "st".
SELECT b.user, a.value as "user1val", b.value as "otheruservalue" FROM st as a
join st as b
on a.user = "user1" and a.user != b.user
where
(b.value > (a.value - 3)) and (b.value < (a.value + 3))
We get unique pairs of user1's value and other user's value by joining same table. After that we just do some simple comparison to filter rows with suitable values.
$user1 = mysql_fetch_assoc(mysql_query("SELECT `value` FROM `users` WHERE id='1'"));
$result = mysql_query("SELECT * FROM `users` WHERE value<'".$user1['value']."+3' OR value>'".$user1['value']."-3'");
Or nested queries :
$result = mysqli_query($con, "select * from `users` where `value` < (select `value` from `users` where `name`='user1')+3 OR `value` > (select `value` from `users` where `name`='user1')-3");
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
I have a table with 3 columns
---QID---TEXT---CID---
I would like to find 20 rows(QID and TEXT) for each distinct CID. I have already prepared string $cid so that I can use WHERE IN statement.
SELECT * FROM questions q1
WHERE cid=(SELECT cid
FROM questions q2
WHERE q2.cid IN ($cids)
GROUP BY q2.cid)
ORDER BY q1.qid LIMIT 20
Thank you!
Simple query:
$query = 'SELECT QID, TEXT FROM yourDb.yourTable WHERE CID = '.$cid;
or, if $cid is an array:
$query = 'SELECT QID, TEXT FROM yourDb.yourTable WHERE CID IN('.implode(',',$cid).')';
To get to the results:
$pdo = new PDO('mysql:host=yourDBServer','login','password');
if (!$stmt = $pdo->query($query))
{
die('query failed');
}
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
For more info on what you can do with the PDO object, refer to the manual
A quick fix (but not a good one) might be:
$q = 'SELECT QID, TEXT FROM yourDB.yourTB WHERE CID = '.$cid.' LIMIT 20';
In the case of CID IN(1,2,3), I'm not sure if there's a strait forward way of doing this. All I can think of is using unions. Mayby this page can help you out with that.
A fugly fix might also be to ORDER BY CID ASC, and insted of using fetchAll(), do this:
$query = 'SELECT CID,QID, TEXT FROM yourDb.yourTable WHERE CID IN('.implode(',',$cid).')';
//execute query, same as above: $stmt holds results
$results = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
if (!is_array($results[$row['CID']))
{
$results[$row['CID']] = array();
}
if (count($results[$row['CID']]) < 20)
{
$results[$row['CID']][] = $row;
}
}
This way, the $results array, will have a key for each CID that was found, and that key's value will be an array of up to 20 records...
The problem is in using the = operator and passing a set of values instead of single one. Change your query to the following and try again
SELECT * FROM questions q1
WHERE cid
IN $cids
ORDER BY q1.qid LIMIT 20
The following snippet uses the MySQL variable trick to assign a number for each row per CID. To keep the example simple I've limited the amount of returned rows to 2 per CID.
select cid
, qid
, text
from (
select if(#last_cid = cid, #rn := #rn + 1, #rn := 1) as rn
, (#last_cid := cid)
, cid
, qid
, text
from YourTable yt
cross join
(select #rn := 0, #last_cid := -1) r
) as SubQueryAlias
where rn < 3;
Data setup:
create table YourTable (QID int, TEXT varchar(50), CID int);
insert YourTable values
(1, 'hi', 1),
(1, 'hi', 1),
(2, 'hi', 1),
(2, 'hi', 1),
(3, 'hi', 2),
(4, 'hi', 2),
(4, 'hi', 2),
(5, 'hi', 3);
This returns up to two rows per CID:
+------+------+------+
| cid | qid | text |
+------+------+------+
| 1 | 1 | hi |
| 1 | 1 | hi |
| 2 | 3 | hi |
| 2 | 4 | hi |
| 3 | 5 | hi |
+------+------+------+
I have 3 columns in table1: book, key and value.
| book | key | value |
------------------------------
| 1 | author | a |
| 1 | editor | b |
| 1 | book | c |
Instead of runnuing three queries
$data = mysql_query("
SELECT * FROM table1 WHERE book = '1' AND key = 'author'
") or die(mysql_error());
while($info = mysql_fetch_array( $data ))
{
$value1 = $info['value'];
}
Then repeat this for editor and book.
$value1 $value2 $value3 are inserted in different places on page
Could I do this with one query?
Yes. If there are no other entries with "book = 1" you just query
SELECT * FROM table1 WHERE book = '1'
If there are more entries you can use this query:
SELECT * FROM table1 WHERE book = '1' AND key IN('author','editor','book')
And then create an assoc array:
while($info = mysqli_fetch_assoc( $data ))
{
$value[$info['key']] = $info['value'];
}
...
echo "the book {$value['book']} was written by {$value['author']}";
for create a $value array you have to use this :
$value[] = $info['value'];
instead of this :
$value1 = $info['value'];
Also you can use this code :
$value[]["key"] = $info['key'];
$value[]["value"] = $info['value'];
And for example you can call first row's value with $value[0]["value"]
If you want the values in a single record try this:
SELECT `t1`.`value` AS `value1`, `t2`.`value` AS `value2`, `t3`.`value` AS `value3`
FROM
`table1` AS `t1` CROSS JOIN
`table1` AS `t2` CROSS JOIN
`table1` AS `t3`
WHERE
(`t1`.`book` = 1) AND (`t1`.`key` = 'author')
AND (`t2`.`book` = 1) AND (`t2`.`key` = 'editor')
AND (`t3`.`book` = 1) AND (`t3`.`key` = 'book');