CodeIgniter - sorting CSV - php

I have a table in my DB with following headers: user, category, title, marks
And values in it are like this
User1 - Food - Pizza - 19
User2 - Drinks - Cola - 18
User2 - Food - Spaghetti - 19
User1 - Food - Potato - 15
User1 - Drinks- Pepsi- 10
User2 - Food - Onion - 11
User1 - Food - Tomato - 10
This is also the way it printed in my CSV file, But what I'm trying to achieve in my CSV file is this format
A(user) B(=category) C D E
1. User 1 Food Pizza -19 Potato - 15 Tomato - 10
2. Drinks Pepsi
3. Empty row
4. User 2 Food Spaghetti-19 Onion-11
5. Drinks Cola-18
6. Empty Row
7. A third user with his category's
This basically what I'm trying to achieve - Sorting the user then sorting the category's that the user has and then at every category the user has print the titles and the scores. But How can I sort and do logic for putting in a CSV?
I have the following code
Model:
function CSV(){
$this->load->dbutil();
$this->db->select('user, category, title, score');
$query = $this->db->get('Table_restaurant_scores');
return $this->dbutil->csv_from_result($query, ";", "\r\n");
}
Controller:
function exporting(){
$this->load->model('restaurant_mdl');
$this->load->helper('download');
$name = 'restaurant_scores.csv';
$data = $this->restaurant_mdl->CSV();
force_download($name, $data);
}
Can someone help me out with this?

It depends on how you fetch your data in your model. You need to add order_by statement in your query e.g
$this->db->order_by("user", "asc");
$this->db->order_by("category", "asc");
// Produces: ORDER BY user DESC, category ASC

Related

unable to sort alphabatically when calling data from db

I am trying to sort alphabetically. I am calling data from database. In the table i am storing ID's of Make like Suzuki, Toyota. I have 1 table naming Make in which i am saving Makes like Toyota.
then i am adding into Models with respect to Make like Land Cruiser is a model and its Make is Toyota. i am inserting ID of the Make from Make's table. then on front end, i am converting the ID's back to Make's name. I want to show Makes name alphabetically.
Here what i do
<?php
$SelectMainCats = mysqli_query($con, "SELECT * FROM model");
$S_NO = 0;
while($row=mysqli_fetch_assoc($SelectMainCats)){
$S_NO++;
$getid = $row['id'];
//converting ids to names
$main_make_query = mysqli_query($con,"SELECT * FROM make WHERE id=".$row['make']);
$main_make = mysqli_fetch_assoc($main_make_query);
?>
Front end calling
<td><?php echo $main_make['maker_name'];?></td>
Running a query and looping through the result set to run more queries is almost always the wrong way to SELECT data. You should be using a JOIN to link the two tables, then one query will retrieve all the data, sorted in the order you want.
Based on this data:
Makes
id makerName
1 Ford
2 Suzuki
3 Toyota
Models
id makerId modelName
1 1 Prefect
2 2 Swift
3 3 LandCruiser
4 3 Celica
5 1 Orion
6 2 Splash
7 1 Mondeo
This Query
SELECT b.makerName, a.modelName FROM models a join makes b on a.makerId = b.id order by makerName;
Gives this result
makerName modelName
Ford Prefect
Ford Orion
Ford Mondeo
Suzuki Swift
Suzuki Splash
Toyota LandCruiser
Toyota Celica

MySQL Query to Select dependent rows from Joined tables

I'm working on a codeigniter project.
Here are my tables
category
cid cname
5 general
6 science
7 math
books
bid bname
12 first
13 second
14 third
15 fourth
16 fifth
17 sixth
dir
id bid cid
1 12 5
2 13 6
3 14 7
4 15 6
5 16 5
6 17 5
As you can see joining the tables is easy but here is what I need to do.
Create a function that will give me category name(cname) and the number of books in that category. For example the outcome should be like
general 3
science 2
math 1
here is my WIP model
function category_details(){
$this->db->order_by('cname','asc');
$query=$this->db->query('Select * from dir join category on category.cid=dir.cid join books on dir.bid=books.bid');
return $query->result_array();
}
Any help would be much appreciated.
The query should be like this to get expected result
Select category.cname,count(dir.cid) from dir join category on category.cid=dir.cid join books on dir.bid=books.bid group by category.cname
And your function should be like this
function category_details(){
$this->db->order_by('cname','asc');
$query=$this->db->query('Select category.cname,count(dir.cid) from dir join category on category.cid=dir.cid join books on dir.bid=books.bid group by category.cname');
return $query->result_array();
}
you can refer this code COUNT / GROUP BY with active record? for proper CI query.

MySQL/PHP - Need to be able to produce query results with certain columns having more weight than others

I have been tasked with creating a search function that when searched, certain fields will have more weight than others.
Here is an simplified example.
cars (table)
year, make, model, color, type (columns)
Let's say someone searches for the following:
Year: 1968
Make: Ford
Model: Mustang
Color: Red
Type: Sports Car
If the cars in the table have none of the correct fields they should not show up, but if record has some of the correct fields but not all they should still show up. But certain fields should be weighted higher than others.
For instance maybe they are weighted like this:
Column - Weight
Year - 30
Make - 100
Model - 85
Color - 10
Type - 50
So if a record matches the search in the "make" field and the "model" field, that record would be above a record that matched in the "year", "color" and "type" field, because of the weights we placed on each column.
So lets say that the query matches at least one field for two records in the database, they should be ordered by the most relevant based on the weight:
1971, Ford, Fairlane, Blue, Sports Car (weight = 185)
1968, Dodge, Charger, Red, Sports Car (weight = 90)
I have been racking my brain trying to figure out how to make this work. If anyone has done something like this please give me an idea of how to make it work.
I would like to do as much of the work in MySQL as possible via joins, I think this will be bring up the results faster than doing most of the work in PHP. But any solution to this problem would be much appreciated.
Thanks in advance
Bear with me, this is going to be a strange query, but it seems to work on my end.
SELECT SUM(
IF(year = "1968", 30, 0) +
IF(make = "Ford", 100, 0) +
IF(model = "Mustang", 85, 0) +
IF(color = "Red", 10, 0) +
IF(type = "Sports Car", 50, 0)
) AS `weight`, cars.* FROM cars
WHERE year = "1968"
OR make = "Ford"
OR model = "Mustang"
OR color = "Red"
OR type = "Sports Car"
GROUP BY cars.id
ORDER BY `weight` DESC;
Basically, this groups all results by their id (which is necessary for the SUM() function, does some calculations on the different fields and returns the weight as a total value, which is then sorted highest-lowest. Also, this will only return results where one of the columns matches a supplied value.
Since I don't have an exact copy of your database, run some tests with this on your end and let me know if there's anything that needs to be adjusted.
Expected Results:
+============================================================+
| weight | year | make | model | color | type |
|============================================================|
| 130 | 1968 | Ford | Fairlane | Blue | Roadster |
| 100 | 2014 | Ford | Taurus | Silver | Sedan |
| 60 | 2015 | Chevrolet | Corvette | Red | Sports Car |
+============================================================+
So, as you can see, the results would list the closest matches, which in this case are two Ford (+100) vehicles, one from 1968 (+30), and a Red Sports Car (10 + 50) as the closest matches (using your criteria)
One more thing, if you also want to display the rest of the results (ie results with a 0 weight match score) simply remove the WHERE ... OR ..., so it will check against all records. Cheers!
Further to the comments below, checking the weight after a LEFT JOIN on a pivot table:
SELECT SUM(
IF(cars.year = "1968", 30, 0) +
IF(cars.make = "Ford", 100, 0) +
IF(cars.model = "Mustang", 85, 0) +
IF(cars.color = "Red", 10, 0) +
IF(types.name = "Sports Car", 50, 0)
) AS `weight`, cars.*, types.* FROM cars
LEFT JOIN cars_types ON cars_types.car_id = cars.id
LEFT JOIN types ON cars_types.type_id = types.id
WHERE year = "1968"
OR cars.make = "Ford"
OR cars.model = "Mustang"
OR cars.color = "Red"
OR types.name = "Sports Car"
GROUP BY cars.id
ORDER BY `weight` DESC;
Here is a picture of the LEFT JOIN in practice:
As you can see, the Cobalt matches on color (silver) and model (Cobalt) (85 + 10) while the Caliber matches on type (Sports Car) (50). And yes, I know a Dodge Caliber isn't a Sports Car, this was for example's sake. Hope that helped!
If I understand your logic you can just do something like direct comparison in PHP between the value requested and the value returned.
The query will sound like:
SELECT Year,Make,Model,Color,Type
FROM table
WHERE year='$postedyear' OR make='$postedmake'
OR model='$postedmodel' OR color='$postedcolor'
Then in php looping between the results:
foreach($results as $result){
$score = 0;
if($result['year']==$postedyear{$score=$score+30;}
//continue with the other with the same logic.
}
After each foreach iteration $score will be the score of that selected row. If you push the score to the $result array you can also sort it by score before displaying the results.
Variation on #lelio-faieta
In php you can have a result array containing arrays of values for each item matching at least one of the search terms, the associative array of values to match and the associate array of weights, both with the same indexes. You would just get an array of matches for each index. (maybe use array_intersect_assoc()) Then you multiply by the weights and sum, add to the original data. Then you do have to sort the result array at that point.
There is a solution doing this via the mysql query directly, but that would end up with an overgrown resource thirsty query for every single search you perform.
Doing it in PHP is not much difference in resource usage, bounding to several loops in results and processing it.
I've had a very similar project and my best suggestion would be: "use SphinxSearch"
Very easy to install, needs a bit of a learning curve to setup afterwards, but very similar to mysql queries etc. With this you can apply weights to every column match and rank your results afterwards.
Also, it is a multitude of time faster that typical mysql queries.

mysql 2 tables updation/deletion based on condition

Hello friends I have 2 Mysql tables with 1:N relationship between category and category_Dates
Category:
ID Category Frequency
1 Cat A Half-yearly
2 Cat B Quarterly
category_Dates:
ID CatID Date
1 1 01-Jan-15
2 1 01-Jul-15
3 2 01-Jan-15
4 2 01-Apr-15
5 2 01-Jul-15
6 2 01-Oct-15
based on the category frequency I am entering number of records automatically in category_date. Eg
When category frequency = quarterly, I am entering 4 records in category_date with ID of that category. And dates will be entered later.
I am little confused if in case on wants to edit the frequency from halfyearly to yearly. How to change number of records. Please help with your valuable suggestions. I am using laravel 4 framework with mysql
best way would be with 3rd table joining Dates and Categories. See little carefully ,you can see its actually Many to Many relationship (N to N) as 1 category can have multiple dates. and one date may be part of multiple categories, like say 01-Jan-15 is part of Category 1 and 2 as well.
So use
category table
id Category Frequency
1 Cat A Half-yearly
2 Cat B Quarterly
date table
id Date
1 01-Jan-15
2 01-Apr-15
3 01-Jul-15
4 01-Oct-15
categories_dates table
ID CatID Date_id
1 1 1
2 1 3
3 2 1
4 2 2
5 2 3
6 2 4
If you change the frequency in Category table, retrieve the update category_id,
delete all from category_dates where CatId=category_id then insert the new entries in category_Dates.
Hope this help.
I assume your models are Category and CategoryDates.
let's update category id 1 from Half-yearlyto to Quarterly
$query = Category::find(1);
$query -> Frequency = 'Quarterly';
$query -> save();
return $query -> id;
in the CategoryDates model you would delete the catID = 1 and insert new data
$catID = 1;
$query = CategoryModel::where('CatId',$catId) -> delete();
$data = ['CatId' => $catID,'date' => 01-Jan-15, ....];
CategoryModel::create($data);
of course assuming that you would return the newly updated category id to your controller and call a funtionn to do the update in your CategoryModel.
Hope this help.

Handling Multi level category structure dynamically

Currently working on the project related to Business listing. I need some help in handing category structure.
Using the table name Bus_CategoryTbl to maintain the categories & used fields are Cat_ID, Cat_Name, Cat_Slug, Cat_Level etc., In this, Cat_PID will have the Cat_ID of the parent category.
Here are the example records,
Cat_ID Cat_name Cat_Slug Cat_PID
1 Web Design web-design 0
2 PHP php 1
3 MYSQL mysql 1
4 Hotels hotels 0
5 5 Stars 5-stars 4
6 3 stars 3-stars 4
7 Le Meridian le-meridian 5
8 St Laurn Suites st-laurn-suites 5
9 Niraali Executive niraali 6
Cat_PID value 0 indicates first level parent category.
Above is the example records, above table have 3 levels. For Ex: Hotels (Cat_ID: 4) -> 5 Stars (Cat_ID: 5) -> St Laurn Suites (Cat_ID: 8)
How the acheive the above result dynamically using PHP/MySql (Levels may increased in future)? It should not utiize more CPU time. current code was written in 3 dimensional array structure using foreach, but its little confused taking more CPU time.
Can you someone help me in achieving this? TIA.
Try following code
function Fname($parentId=0){
$catgArray = array();
$sql = mysql_query("SELECT * FROM Table Where Cat_PID=$parentId");
$mainCatg = mysql_fetch_array($sql);
foreach($mainCatg as $mc){
array_push($catgArray , $mc);
$subCatg = $this->Fname($mc->Cat_ID);
if (count($subCatg ) > 0) {
array_push($catgArray , $subCatg );
}
}
return $catgArray;
}
In the Result we can check the sub category levels by using is_array() function

Categories