How do I count multiple columns with a vertical value? - mysql

I'm new to programing. I have table
check_1,check_2,check_3 ..etc
------------------------------
1 1 1
0 0 1
1 0 1
And I want this output :
column_name, count_true
-----------------------
check_1 2
check_2 1
check_3 3
I've tried it with mysql using the union function, but when I try to apply it in laravel I have trouble with union. Is there a unionless query that can produce such output?
Thanks in advance

You can do this way. One query in db
$records = DB::table('your_table')->get();
$check1Count = $records->where('check_1', 1)->count();
$check2Count = $records->where('check_2', 1)->count();
$check3Count = $records->where('check_3', 1)->count();
......
Or
$records = DB::table('your_table')->get();
$columns = ['check_1', 'check_2', 'check_3', ...];
$data = [];
foreach($columns as $column) {
$data[] = [
'column_name' => $column,
'count_true' => $records->where($column, 1)->count();
];
}
Also you can do this way but it is many query
$check1Count = DB::table('your_table')
->selectRaw('COUNT(check_1) as count')
->where('check_1', 1)
->first()
->count;
$check2Count = DB::table('your_table')
->selectRaw('COUNT(check_2) as count')
->where('check_2', 1)
->first()
->count;
.....

A normalised approach might look like this:
response_id checkbox
1 1
1 2
1 3
2 3
3 1
3 3

You don't need union, just query all the data and process it on Laravel. Let say you query all the data using eloquent to $data variable, then you should do it like this:
//preparing a variable to hold all 24 database field value
$total = [];
foreach ($data as $d) {
//do this for all 24 database field
if ($d->check_1) {
$total[1]++;
}
if ($d->check_2) {
$total[2]++;
}
...
}
By using that way you can't check the resutl on $total[index] variable. And yes, there is a better way to store your data instead of saving all the field for each user. You can just store all checked value in database that look like this :
user_id checkbox_id
1 3
1 5
1 9
1 24
2 23
3 2
3 3
It more efficient since you don't need to save the unchecked checkbox value, if they more likely not to checked most of the checkbox.

Related

Laravel orWhereIn and orWhereIn and so on

To be honest I rly do not know how to describe my query problem, hope example will clear things up:
I've got simple query:
return $query->whereHas('categories', function ($q) use ($ids) {
$q->whereIn('category_id', $ids);
}, '=', count($ids));
which returns records that match array of categories ids. To present this better right now we've got such condition
getRecordsThatMatchThisCondition(id1 && id2 && id3... and so on).
What I want is to achieve such comparasion
getRecordsThatMatchThisCondition((id1.1 || id1.2 || id1.3) && (id2.1 || id2.2) ... and so on.)
I've couldn't find any help with this problem so far. Even naming such query would be helpfull. My table is simple PIVOT
id record_id category_id
------------------------------------
1 1 35
2 2 41
3 2 74
4 3 74
5 3 40
6 4 40
Summarizing my problem with words:
I do not have record relation to parent_category of selected category... Right now I need to display all records that match multiple categories.
Visualising problem:
Record is assigned to categories like this:
35
└40
└41 ☑
36
└74 ☑
By providing id 35 and 36, record should be found! By providing 40, 74 should NOT be found...
Hope I've described my problem well enough.
You can't query with whereIn method like this, but can use a foreach loop, like this :
return $query->whereHas('categories', function ($q) use ($ids) {
foreach($ids as $key => $value) {
$q->orWhere('category_id', $value)
}
}, '=', count($ids));
Or, with for loop :
return $query->whereHas('categories', function ($q) use ($ids) {
for ($i = 0; $i < count($ids); $i++){
$q->orWhere('category_id', $ids[$i]);
}
}, '=', count($ids));

How to get the all child rows recursively using CodeIgniter and MySQL?

How to get the all child rows and their child rows using CodeIgniter and MySQL?
Here is the Table structure
Id user_id sponser_id
1 1 0
2 2 1
3 3 1
4 4 1
5 5 2
6 6 2
7 7 2
8 8 3
9 8 3
10 10 4
I want to get all the child row which is connected under particular sponser_id. I have trid this query but I can't get proper detail.
$this->db->select('u_fname,u_lname,sponsor_id');
$this->db->from('user_reg');
$this->db->where('sponsor_id', $user_data['otc_id']);
$query = $this->db->get();
Here is the graphical representation of what i am doing. I want all children row of A and same as b to O.
I am calling this function from my controller to get the desired output.
Controller Code:
public function index()
{
$all_level_array = array();
$user_data = $this->common->user_data_db();
$get_user_level = $this->u_buildup_wallet_model->get_user_buildup_level($user_data['otc_id']);
if(!empty($get_user_level)){
foreach ($get_user_level as $userData) {
$test = $this->u_buildup_wallet_model->get_user_buildup_level($userData['otc_id']);
print_r($test);
}
}
print_r($all_level_array);
exit
$this->load->view();
}
Model Code:
public function get_user_buildup_level($user_otc)
{
$this->db->select('u_fname,u_lname,sponsor_id,otc_id');
$this->db->from('user_reg');
$this->db->where('sponsor_id', $user_otc);
$query = $this->db->get();
$result = $query->result_array();
return $result;

Getting an empty result for newQuery

I've a problem in getting the value of the query $scholars for $lt = $scholars->lat.The result is empty array for dd($lt);
.Any help would be helpful to my school project.
database of Scholar
id lat lng scholar_birthday scholar_GPA
1 10.275667 123.8569163 1995-12-12 89
2 10.2572114 123.839243 2000-05-05 88
3 9.9545909 124.1368558 2002-05-05 89
4 10.1208564 124.8495005 2010-05-05 85
$scholars = (new Scholar)->newQuery()->select('*');
$scholars->whereBetween(DB::raw('TIMESTAMPDIFF(YEAR,scholars.scholar_birthday,CURDATE())'),array($ship_age_from,$ship_age_to));
$scholars->whereBetween(DB::raw('scholar_GPA'),array($ship_gpa_from,$ship_gpa_to));
$lt = $scholars->lat;
$lg = $scholars->lng;
$str = $lt.','.$lg;
$url = 'http://maps.googleapis.com/maps/api/geocode/json?latlng='.trim($lt).','.trim($lg).'&sensor=false';
$json = #file_get_contents($url);
$data=json_decode($json);
$status = $data->status;
$data->results[0]->formatted_address;
dd($lt);
$scholars = $scholars->get();
dd Result
Undefined property: Illuminate\Database\Eloquent\Builder::$lat
Two things,
when you use the newQuery() you will still need to get() the result like such
$scholars = (new Scholar)->newQuery()->select('*')->get();
This however will retrieve a collection and not a single result so you will need to loop over this.
foreach($scholars as $scholar){
$lt = $scholars->lat;
dd($lt);
}

Binary search in a MySQL table with deleted rows PHP

I have a large MySQL table with sorted data. When I need to find a starting point, I perform a binary search to find the lower bound ID (auto increment). The only problem is once some data is deleted, I need to look at the first existing row with a lower ID if the ID given by the algorithm doesn't exist. How should I modify this code to achieve that?
$l = 1;
$h = $max; //SELECT MAX(id)
while ($h - $l > 1){
$m = ($h + $l) / 2;
$q = mysqli_query($db, "SELECT col FROM tab WHERE id=". floor($m));
$result = array();
while($result[] = mysqli_fetch_row($q)){;}
if ($result[0][0] < $val) $l = $m;
else $h = $m;
}
echo round($m);
For example I want to find which rows have the value of col greater than 12345 and the table has max ID 10000. I start by looking at row 5000, where the col = 9000, then 7500 (col = 13000), then 6250 has been deleted, so I start looking for the 1st existing row with ID < 6250 and I find that 6245 has col = 10500. Now I'm looking between IDs 6873 and 7500 etc.
The right way to do this
So you have a table like this:
| ID | col |
---------------
| 1 | 15 |
| 3 | 155 |
| 18 | 9231|
| 190 |14343|
| 500 |16888|
You can get find 14343 with the following query:
SELECT ID, col FROM the_table WHERE col>12345 LIMIT 1;
To make it faster, you'd need to add an index (index word is worth googling)
ALTER TABLE `the_table` ADD INDEX `col` (`col`);
After that mysql will create a tree structure internally and will be doing binary searches on it for you.
This will be working much faster as you'll avoid multiple network roundtrips + other per request expenses (query parsing, optimization, all the locks & mutexes, ...)
Answer to your question
I need to look at the first existing row with a lower ID
E.g. you'd like to get first row with an ID < than 300, you do this (limit is what makes the query return only 1 result):
SELECT col FROM the_table WHERE ID < 300 LIMIT 1;

php script to move data between columns with mysql

What I want to achieve is to move the data between 2 rows within one table.
Column A
--------
FN2
1 200x310mm
2 400x260mm[+0.84]
3 500x500mm[+11.34]
Column B
--------
0.0000
0.0000
0.0000
0.0000
This is how it should look like after the data move:
Column A
--------
FN2
1 200x310mm
2 400x260mm
3 500x500mm
Column B
--------
0.0000
0.0000
+0.84
+11.34
What I want is that the query between the [ ] is moved to column B and replaces the 0.0000
How can I achieve this?
Kind Regards
just to illustrate what Yadav said
$query = "SELECT columnID, columnA FROM table";
$result = mysql_query($query,$conn);
while ($row = mysql_fetch_array($result)){
$id = $row['columnID'];
$a = $row['columnA'];
$pos1 = strpos($a,"[")+1;
$pos2 = strpos($a,"]");
$b = substr($a,$pos1,$pos2-$pos1);
$query = "UPDATE table SET columnB = $b WHERE columnID = $id";
mysql_query($query,$conn);
}//end while
edit: Yadav obviously proposed a better answer while I was typing mine...
try this it works for you here i used id as unique key ... and test is my database
<?php
$con=mysql_connect("localhost","root","");
$db=mysql_select_db("test");
$query=mysql_query("SELECT * FROM test where columnA LIKE '%[%]'");
while($row=mysql_fetch_assoc($query))
{
if(preg_match_all('/\[(.*?)\]/',$row['columnA'],$match))
{
mysql_query("UPDATE test SET columnB='".$match[1][0]."' WHERE id=".$row['id']."");
}
}
?>