Export data from SQL to CSV with modified format - mysql

Suppose I have a table in SQL named 'myTable'. It contains 3 columns; 'id', 'lat' and 'lng'
| id | lat | lng |
|------+--------+--------|
| 1 | 1.11 | 1.22 |
| 2 | 2.11 | 2.22 |
| 3 | 3.11 | 3.22 |
| 4 | 4.11 | 4.22 |
| .... | .... | .... |
I want to export it to CSV. I expect the result become like this in the CSV file :
| | A | B | C | D | ....
------+-----+------+--------+------+--------
| 1 | 1.11 | 2.11 | 3.11 | 4.11 | .... //contains 'lat'
| 2 | 1.22 | 2.22 | 3.22 | 4.22 | .... //contains 'lng'
Can you help me? I'm using PHP. Thanks a lot.

This might actually be something which would be best handled in your PHP script, rather than in MySQL. Assuming your are using mysqli, you could try something like this:
$sql = "SELECT id, lat, lng FROM yourTable ORDER BY id";
$result = $conn->query($sql);
$row1 = NULL;
$row2 = NULL;
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
if ($row1 != NULL) {
$row1 .= ",";
$row2 .= ",";
}
$row1 .= $row["lat"];
$row2 .= $row["lng"];
}
}
At the end of the loop in the above script, $row1 and $row2 should contain the first two rows of the output file you expect. The only steps missing might be the header, if you want that, and also the details of how to write a string to a text file.

Related

MySQL SUM returns unexpected value

I've been trying to use SUM() to total up some numeric values in my database, but it seems to be returning unexpected values. Here is the PHP-side for generating the SQL:
public function calcField(string $field, array $weeks)
{
$stmt = $this->conn->prepare('SELECT SUM(`'. $field .'`) AS r FROM `ws` WHERE `week` IN(?);');
$stmt->execute([implode(',', $weeks)]);
return $stmt->fetch(\PDO::FETCH_ASSOC)['r'];
}
Let's give it some example data for you folks at home:
$field = 'revenue';
$weeks = [14,15,16,17,18,19,20,21,22,23,24,25,26];
This returns this value:
4707.92
Without seeing the data, this may have seemed to have worked, but here's the rows for those weeks:
+----+------+------+---------+-------+---------+---------+------+----------+
| id | week | year | revenue | sales | gpm_ave | uploads | pool | sold_ave |
+----+------+------+---------+-------+---------+---------+------+----------+
| 2 | 14 | 2019 | 4707.92 | 292 | 13 | 0 | 1479 | 20 |
| 3 | 15 | 2019 | 4373.32 | 304 | 13 | 0 | 1578 | 19 |
| 4 | 16 | 2019 | 4513.10 | 275 | 14 | 0 | 1460 | 19 |
| 5 | 17 | 2019 | 4944.80 | 336 | 14 | 0 | 1642 | 20 |
| 6 | 18 | 2019 | 4343.87 | 339 | 13 | 0 | 1652 | 21 |
| 7 | 19 | 2019 | 3918.59 | 356 | 14 | 0 | 1419 | 25 |
| 8 | 20 | 2019 | 4091.20 | 247 | 19 | 0 | 1602 | 15 |
| 9 | 21 | 2019 | 4177.22 | 242 | 12 | 0 | 1588 | 15 |
| 10 | 22 | 2019 | 3447.88 | 227 | 18 | 0 | 1585 | 14 |
| 11 | 23 | 2019 | 3334.18 | 216 | 15 | 0 | 1675 | 13 |
| 12 | 24 | 2019 | 4736.15 | 281 | 13 | 0 | 1388 | 20 |
| 13 | 25 | 2019 | 4863.84 | 252 | 12 | 0 | 1465 | 17 |
| 14 | 26 | 2019 | 4465.95 | 281 | 21 | 0 | 1704 | 16 |
+----+------+------+---------+-------+---------+---------+------+----------+
As you can see, the total should be far greater than 4707.92 - and I notice that the first row revenue = 4707.92.
Here's what things get weird, if I add this into the function:
echo 'SELECT SUM(`'. $field .'`) AS r FROM `ws` WHERE `week` IN('. implode(',', $weeks) .');';
Which outputs:
SELECT SUM(revenue) AS r FROM ws WHERE week IN(14,15,16,17,18,19,20,21,22,23,24,25,26);
Copying and pasting this into MySQL CLI returns:
MariaDB [nmn]> SELECT SUM(revenue) AS r FROM ws WHERE week IN(14,15,16,17,18,19,20,21,22,23,24,25,26);
+----------+
| r |
+----------+
| 55918.02 |
+----------+
1 row in set (0.00 sec)
Which, looks a lot more accurate. However, that very same SQL statement returns the first row value rather than summing the column for those weeks.
This function gets triggered by an AJAX script:
$d = new Page\Snapshot\D();
# at the minute only outputting dump of values to see what happens
echo '<pre>'. print_r(
$d->getQuarterlySnapshot(new Page\Snapshot\S(), new App\Core\Date(), $_POST['quarter'], '2019'),
1
). '</pre>';
The function $d->getQuarterlySnapshot function:
public function getQuarterlySnapshot(S $s, Date $date, int $q, string $year)
{
switch($q)
{
case 1:
$start = $year. '-01-01 00:00:00';
$end = $year. '-03-31 23:59:59';
break;
case 2:
$start = $year. '-04-01 00:00:00';
$end = $year. '-06-30 23:59:59';
break;
case 3:
$start = $year. '-07-01 00:00:00';
$end = $year. '-09-30 23:59:59';
break;
case 4:
$start = $year. '-10-01 00:00:00';
$end = $year. '-12-31 23:59:59';
break;
}
$weeks = $date->getWeeksInRange('2019', 'W', $start, $end);
foreach ($weeks as $key => $week){$weeks[$key] = $week[0];}
return [
'rev' => $s->calcField('revenue', $weeks),
'sales' => $s->calcField('sales', $weeks),
'gpm_ave' => $s->calcField('gpm_ave', $weeks),
'ul' => $s->calcField('uploads', $weeks),
'pool' => $s->calcField('pool', $weeks),
'sold_ave' => $s->calcField('sold_ave', $weeks)
];
}
So I don't overwrite the value anywhere (that I can see at least). How do I use SUM() with the IN() conditional?
As pointed out in the comments by #MadhurBhaiya:
Comma separated week_id values is passing as a single string in the query: week_id in ('1,2,3...,15') . MySQL implicitly typecasts this to 1 and thus gets the first row only. You will need to change the query preparation code
Led me to breaking up the single ? into named parameters using a foreach loop:
public function calcField(string $field, array $weeks)
{
$data = [];
$endKey = end(array_keys($weeks));
$sql = 'SELECT SUM(`'. $field .'`) AS r FROM `ws` WHERE `week` IN(';
foreach ($weeks as $key => $week)
{
$sql .= ':field'. $key;
$sql .= ($key !== $endKey ? ',' : '');
$data[':field'. $key] = $week;
}
$sql .= ');';
$stmt = $this->conn->prepare($sql);
$stmt->execute($data);
return $stmt->fetch(\PDO::FETCH_ASSOC)['r'];
}
Now each numeric value is treated individually, which, is getting me the expected value.
Yes, it is showing only first row data in your query because you have mentioned where week IN (1,2,3,4,5,6,7,8,9,10,11,12,13); and your data shows that you have week 13 and 1 to 12 does not exist in your data from IN clause of your query.
You are selecting only the row with week 13, the week 1-12 is not existing in your data. That's why the result of your query is 43.900001525878906
Solution 1:
You might want to change the values in your IN()because you are filtering your data by the column week.
SELECT SUM(`revenue`) as `r` FROM `ws` WHERE `week` IN (13,14,15,16,17,18,19,20,21,22,23,24,25);
Solution 2:
You can change the week in your where clause to id
SELECT SUM(`revenue`) as `r` FROM `ws` WHERE `id` IN (1,2,3,4,5,6,7,8,9,10,11,12,13);

how to tokenize string in record to be row

I have the data in a database table named term like this :
---------------------------------------
id_term | keyword |
------- | -----------------------------
1 | how to make search engine |
2 | application engineering |
3 | android application example |
--------------------------------------
then I want it to be like this table :
----------------------------------
| id_term | keyword |
----------------------------------
1 | how |
1 | to |
1 | Make |
1 | search |
1 | engine |
2 | application |
2 | engineering |
3 | example |
3 | application |
3 | android |
----------------------------------
I've tried googling to find references to split the string, but still have not found the appropriate expectations. In an experiment that I've done using substring_index results I could actually like this:
---------------------------------------
id_term | keyword |
------- | -------------------------------
1 | how to make search engine |
1 | how to make search engine |
1 | how to make search engine |
--------------------------------------
there anything you can help me or has the solution of my problem? mysql code that I try something like this:
select term.id_kata, SUBSTRING_INDEX (SUBSTRING_INDEX (term.keyword, ',', term.id_kata), ',', -1) keyword term from inner join keyword_doc on CHAR_LENGTH (term.keyword) -CHAR_LENGTH (REPLACE (term.keyword , ',', ''))> = term.id_kata-1 ORDER BY `term`.`keyword` DESC
I've tried googling for approximately 5 hours to find a solution, but have not found until I was confused to be asked where. there any ideas or can help provide a solution?
The solution for it problem is please take 'BETWEEN' in SQL SYNTAX. this code 100% work for it problem :
<?php
#connection
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = 'pasword';
$dbname = 'yourdatabasename';
error_reporting(E_ALL ^ E_DEPRECATED);
mysql_connect($dbhost,$dbuser,$dbpass) or die(mysqli_error('cannot connect to the server'));
mysql_select_db($dbname) or die(mysqli('database selection problem'));
$frequency = array();
$datastring = 'SELECT id_term,keyword FROM data_token WHERE id_term BETWEEN 1 AND 3';
mysql_select_db('yourdatabasename');
$calldata = mysql_query($datastring);
while($takedata = mysql_fetch_array($calldata,MYSQL_ASSOC))
{
$array = explode("\n",$takedata['keyword']);
foreach ($array as $index => $keyword)
{
if(! array_key_exists($keyword,$frequency))
{
$frequency[$keyword] = 1;
}
else
{
$frequency[$keyword] = $frequency[$keyword] + 1;
}
}
$document = $takedata['id_term'];
foreach ($frequency as $term => $tf)
{
$sqlInput = "INSERT INTO yourtablename (id_term,keyword,frequency) VALUES ('$dokumen','{$term}', {$tf})";
mysql_query($sqlInput);
}
}
?>

Need a SQL query to get a value by joining two table in codeigniter

I have two tables.
Table 1: table_company
+---------------------------+
| company_id | company_name |
+---------------------------+
| 1 | Apple |
| 2 | Samsung |
+---------------------------+
Table 2: table_products
+------------+--------------+-------------+-----------+
| product_id | product_name | category_id |company_id |
+-----------------------------------------------------+
| 1 | iPhone | 3 | 1 |
| 2 | galaxy | 3 | 2 |
| 1 | iPad | 4 | 1 |
| 2 | tab | 4 | 2 |
+-----------------------------------------------------+
I want to join this 2 tables to get the company name according to category_id.
I wrote the following code in my model. but did not get anything. Please help.
public function select_company_by_category_id($category_id) {
$this->db->select('*');
$this->db->from('tbl_products');
$this->db->join('tbl_company', 'company_id = company_id');
$this->db->where('category_id', $category_id);
$query_result = $this->db->get();
$result = $query_result->result();
return $result;
}
try to replace your join with this:
$this->db->join('tbl_company', 'tbl_company.company_id = tbl_products.company_id');
you can find more examples in codeigniter active record page
Use Left Join for this
public function select_company_by_category_id($category_id) {
$this->db->select('*');
$this->db->from('table_products');
$this->db->join('table_company', 'table_company.company_id = table_products.company_id', 'left'); # Changed
$this->db->where('table_products.category_id', $category_id); # Changed
$query = $this->db->get(); # Improved
$result = $query->result_array(); # Improved
return $result;
}
First of all open your database error from database.php file only on development line not on production.
Than issue is that company_id is available in both tables with same name than you must need to add table alias as:
public function select_company_by_category_id($category_id)
{
$this->db->select();
$this->db->from('table_products');
$this->db->join('table_company', 'table_company.company_id = table_products.company_id');
$this->db->where('table_products.category_id', $category_id);
$query = $this->db->get();
$result = $query->result_array();
return $result;
}

How do I insert multiple value if there is only one value in form

I need to know how can I insert or update a value in my DB for a invoice form if the value of the input that I need to save is only one time?
I have a invoice form where I select a product in every row, and finally I have the input(user_id) with the value I need to save with the rest of the inputs
Like per example, I choose in the invoice:
10 tomatoes
5 garlics
2 beans
and finally there is my Id (user_id, not the Id of PRODUCTOS table that is unique)
Id=1
Here is the schema of my table, and how save or update until now:
| cantidad | nombre del producto | Id |
+------------+---------------------+-------+
| 10 | Tomatoes | 1 |
| 5 | garlics | 0 |
| 2 | beans | 0 |
Here what I need to save or update:
| cantidad | nombre del producto | Id |
+------------+---------------------+-------+
| 10 | Tomatoes | 1 |
| 5 | garlics | 1 |
| 2 | beans | 1 |
Here is the code:
$conn->beginTransaction();
$sql = "INSERT INTO PRODUCTOS
(cantidad, nombreProd, Id)
VALUES ";
$insertQuery = array();
$insertData = array();
foreach ($_POST['cantidad'] as $i => $cantidad) {
$insertQuery[] = '(?, ?, ?)';
$insertData[] = $_POST['cantidad'][$i];
$insertData[] = $_POST['nombreProd'][$i];
$insertData[] = $_POST['Id'][$i];
}
if (!empty($insertQuery)) {
$sql .= implode(', ', $insertQuery);
$stmt = $conn->prepare($sql);
$stmt->execute($insertData);
}
$conn->commit();
Thank you
So you have a single userID you want to INSERT for each product record. I can probably provide a better answer if you post the output of print_r($_POST), but basically in your foreach $POST loop, keep the user ID static:
foreach ($_POST['cantidad'] as $i => $cantidad) {
$insertQuery[] = '(?, ?, ?)';
$insertData[] = $_POST['cantidad'][$i];
$insertData[] = $_POST['nombreProd'][$i];
$insertData[] = $_POST['Id']; //OR $insertData[] = $_POST['Id'][0], depending on $_POST array
}

Count and select all dates for a specific field in MySQL

i have a data format like this:
+----+--------+---------------------+
| ID | utente | data |
+----+--------+---------------------+
| 1 | Man1 | 2014-02-10 12:12:00 |
+----+--------+---------------------+
| 2 | Women1 | 2015-02-10 12:12:00 |
+----+--------+---------------------+
| 3 | Man2 | 2016-02-10 12:12:00 |
+----+--------+---------------------+
| 4 | Women1 | 2014-03-10 12:12:00 |
+----+--------+---------------------+
| 5 | Man1 | 2014-04-10 12:12:00 |
+----+--------+---------------------+
| 6 | Women1 | 2014-02-10 12:12:00 |
+----+--------+---------------------+
I want to make a report that organise the ouptout in way like this:
+---------+--------+-------+---------------------+---------------------+---------------------+
| IDs | utente | count | data1 | data2 | data3 |
+---------+--------+-------+---------------------+---------------------+---------------------+
| 1, 5 | Man1 | 2 | 2014-02-10 12:12:00 | 2014-04-10 12:12:00 | |
+---------+--------+-------+---------------------+---------------------+---------------------+
| 2, 4, 6 | Women1 | 3 | 2015-02-10 12:12:00 | 2014-03-10 12:12:00 | 2014-05-10 12:12:00 |
+---------+--------+-------+---------------------+---------------------+---------------------+
All the row thath include the same user (utente) more than one time will be included in one row with all the dates and the count of records.
Thanks
While it's certainly possible to write a query that returns the data in the format you want, I would suggest you to use a GROUP BY query and two GROUP_CONCAT aggregate functions:
SELECT
GROUP_CONCAT(ID) as IDs,
utente,
COUNT(*) as cnt,
GROUP_CONCAT(data ORDER BY data) AS Dates
FROM
tablename
GROUP BY
utente
then at the application level you can split your Dates field to multiple columns.
Looks like a fairly standard "Breaking" report, complicated only by the fact that your dates extend horizontally instead of down...
SELECT * FROM t ORDER BY utente, data
$lastutente = $lastdata = '';
echo "<table>\n";
while ($row = fetch()) {
if ($lastutente != $row['utente']) {
if ($lastutente != '') {
/****
* THIS SECTION REF'D BELOW
***/
echo "<td>$cnt</td>\n";
foreach ($datelst[] as $d)
echo "<td>$row[data]</td>\n";
for ($i = count($datelst); $i < $NumberOfDateCells; $i++)
echo "<td> </td>\n";
echo "</tr>\n";
/****
* END OF SECTION REF'D BELOW
***/
}
echo "<tr><td>$row[utente]</td>\n"; // start a new row - you probably want to print other stuff too
$datelst = array();
$cnt = 0;
}
if ($lastdata != $row['data']) {
datelst[] = $row['data'];
}
$cnt += $row['cnt']; // or $cnt++ if it's one per row
}
print the end of the last row - see SECTION REF'D ABOVE
echo "</table>\n";
You could add a GROUP BY utente, data to your query above to put a little more load on mysql and a little less on your code - then you should have SUM(cnt) as cnt or COUNT(*) as cnt.