For example
I have several profile tables, such as
music_profile
sports_profile
art_profile
All of these tables have matching names, and they all have a title column.
A second table contains alternative titles per any given profile table's row.
Their columns are essentially:
id, parent_id, parent_table, alt_title_001, alt_title_002, alt_title_003, alt_title_004, status, created, updated.
I want to
SELECT multiple column values
FROM music_profile, sports_profile, art_profile
WHERE title, alt_title_001, alt_title_002, alt_title_003, alt_title_004 are like a value
I can currently select columns using WHERE title LIKE and UNION, but I have no idea how to combine the alternate_titles table in the SELECT statement.
I've provided my current code below. The table for alternate_titles has not been implemented here.
I don't necessarily want a coded solution to this issue; I would just like a hint to get me on my way.
sub AdvancedSearchFormResults {
my $self = shift;
my $opts = ref $_[0] eq 'HASH' ? shift : {#_};
my $mode = shift;
my $order = shift;
my $limit = shift;
my #array;
my $where;
my $mode = $$opts{mode};
my $left_join_clause;
my (#where_stmt, #where_vals, #join);
if (defined $$opts{platform}) {
$where = $$opts{platform};
}
if ($$opts{'title_like'}) {
push(#where_stmt, "title like ?");
push(#where_vals, '%'.$$opts{'title_like'}.'%');
}
if ($$opts{'publisher'}) {
push(#where_stmt, "publisher = ?");
push(#where_vals, $$opts{'publisher'});
}
if ($$opts{'status'}) {
push(#where_stmt, "status = ?");
push(#where_vals, $$opts{'status'});
}
my $left_join_clause = scalar #join ? join("\n", #join) : "";
my $where_clause = #where_stmt ? "WHERE ".join(" AND ", #where_stmt) : "";
my $order_clause = length($order) ? "ORDER BY $order" : "";
my $limit_clause = length($limit) ? "LIMIT $limit" : "";
my $select_stmt;
if ($mode eq 'BUILD') {
$select_stmt = "SELECT
'$where' AS event,
ident,
title,
publisher
FROM $where
$left_join_clause
$where_clause
$order_clause
$limit_clause";
my $sth = $schema->prepare($select_stmt) or die $schema->errstr;
$sth->execute(#where_vals) or die $sth->errstr;
while (my $row = $sth->fetchrow_hashref()) {
push(#array, $row);
}
}
elsif ($mode eq 'UNION') {
my #select_stmts;
my #platforms = $self->ProfileTables();
my $total_platforms = -1;
foreach my $table (#platforms) {
$total_platforms++;
my $stmt = "(SELECT '$table' AS event,ident,title,publisher,status FROM $table $where_clause)";
push(#select_stmts, $stmt);
}
my $select_stmt .= "$select_stmts[0] UNION ALL";
$select_stmt .= join(' UNION ALL ', #select_stmts[ 1 .. 28 ]);
my #new_vals = (#where_vals, (#where_vals) x $total_platforms);
my $sth = $schema->prepare($select_stmt) or die $schema->errstr;
$sth->execute(#new_vals) or die $sth->errstr;
while (my $row = $sth->fetchrow_hashref()) {
push(#array, $row);
}
}
elsif ($mode eq 'REFRESH') {
print '
<div class="alert alert-danger" role="alert">
<strong>Please fill out at least one field.</strong>
</div>';
}
return #array;
}
A practical application of the code is below.
These variables are used as an example. This data would normally be supplied via a form.
my $title = 'Mario';
my $publisher = '';
my %params = (
title_like => $title,
publisher => $publisher,
status => 'a',
);
my #results = $results->AdvancedSearchFormResults(\%params);
print Data::Dumper::Dumper(\#results);
Dumper Results
$VAR1 = [
{
'ident' => '2109',
'title' => 'Mario Bros.',
'publisher' => 'Atari'
},
{
'ident' => '30',
'title' => 'Mario Bros.',
'publisher' => 'Atari'
},
{
'publisher' => 'Atari',
'ident' => '43',
'title' => 'Mario Bros.'
},
];
After a bit of headache and some intense googling I was able to come up with a solution.
The most basic solution to my problem is:
my #profiles = ('art', 'music', 'sports');
my #results;
my $blah;
my $sql;
foreach my $profile (#profiles) {
$sql = "SELECT
$profile.ident,
$profile.title,
$profile.status
FROM $profile
LEFT JOIN alternate_titles ON $profile.ident = alternate_titles.parent_ident
WHERE title like '%$blah%'
OR
CONCAT_WS(' ',alternate_titles.alt_title_001,alternate_titles.alt_title_002,alternate_titles.alt_title_003,alternate_titles.alt_title_004
AND alternate_titles.parent_table = '$profile'";
}
my $sth = $schema->prepare($sql) or die $schema->errstr;
$sth->execute() or die $sth->errstr;
while (my $data = $sth->fetchrow_hashref()) {
push(#results, $data);
}
This isn't immediately implementable in my code example, but this works as a great starting point.
I don't know that this is efficient, if anyone has a better solution, I'd love to see it.
Related
Am using drupal to manage my content. I want to search all my contents title and body and find how many times each word is repeated in the whole contents.
It may be by an sql query, but I have no experience with sql.
Any ideas?
This code searches the body field and ALL fields of ANY Content Types for a specific string. You can run it via command line. Say you save it as "fieldsearch.php", you can then run it as:
php fieldsearch.php "myStringForWhichToSearch"
You need to fill in your connection data and database name. It outputs the array of matching nodes but you can format that output into anything you'd like (I recommend csv).
<?php
//Set Parameters here
$env = "dev"; // Options [dev|prod] - Defaults to dev
$prodConnection = array(
"host" => "",
"user" => "",
"pass" => ""
);
$devConnection = array(
"host" => "",
"user" => "",
"pass" => ""
);
//Use the selected env settings
if($env == "prod"){
$connection = $prodConnection;
} else {
$connection = $devConnection;
}
function getTables($con, $database){
//Get the set of field tables
$sql = "SHOW TABLES FROM $database";
$result = mysqli_query($con, $sql);
if (!$result) {
echo "DB Error, could not list tables\n";
echo 'MySQL Error: ' . mysql_error();
exit;
}
$tables = array();
while ($row = mysqli_fetch_row($result)) {
$tables[] = $row[0];
}
mysqli_free_result($result);
return $tables;
}
function getFieldTables($con,$database){
$allTables = getTables($con, $database);
$fieldTables = array();
foreach($allTables as $key => $table){
if( isFieldTable($table) ){
$fieldTables[] = $table;
}
}
//add the common tables
$fieldTables[] = "field_data_body";
$fieldTables[] = "field_data_comment_body";
return $fieldTables;
}
function isFieldTable($table){
//echo $table . "\n";
if( stripos($table, "field_data_field") !== FALSE){
return TRUE;
}
}
//Set the search term here:
if (array_key_exists(1, $argv)) {
$searchString = $argv[1];
}
else {
die('usage: php fieldsearch.php "search string"' . "\n");
}
$databaseName = "myDatabaseName";
$outArray = array();
//Connect
$con=mysqli_connect($connection['host'],$connection['user'],$connection['pass'],$databasePrefix.$databaseNum);
// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
//getFieldTables
$fieldTables = getFieldTables($con, $databaseName);
//Query each field tables data for the string in question
foreach($fieldTables as $key => $table){
//get Field value column name
$valueCol = str_replace("field_data_field_", '', $table);
$result = mysqli_query($con,"SELECT
entity_id
FROM
$table
WHERE
field_" . $valueCol . "_value
LIKE
'%$searchString%';");
if($result){
while($row = mysqli_fetch_assoc($result)){
$dataArray[$table][$row['entity_id']]['nid'] = $row['entity_id'];
}
}
}
//Add the body table
$result = mysqli_query($con,"SELECT
entity_id
FROM
field_data_body
WHERE
body_value
LIKE
'%$searchString%';");
if($result){
while($row = mysqli_fetch_assoc($result)){
$dataArray['field_data_body'][$row['entity_id']]['nid'] = $row['entity_id'];
}
}
var_dump($dataArray);
I need to store two values in the same column. These are the code and name, separated by a hyphen. How can I do this using this array?
'name'=> $data['code']['name']
I read about serialization, but I do not see how to implement it here.
public function addProduct($code, $name, $photo, $data = array())
{
if($photo == NULL) {
// Product data
$productData = array(
'code' => $data['code'],
'name' => $data['name'],
'category_id' => $data['category_id'],
'subcategory_id' => $data['subcategory_id'],
);
} else {
// Product data
$productData = array(
'code' => $data['code'],
'name' => $data['name'],
'category_id' => $data['category_id'],
'subcategory_id' => $data['subcategory_id'],
'image' => $photo
);
}
if($this->db->insert('products', $productData)) {
return true;
} else {
return false;
}
}
If I understand correctly, I think you want this:
'name' => serialize(array('code'=>$data['code'], 'name'=>$data['name']))
Then to retrieve it you can simply
$data = unserialize($res['name']);
echo $data['code']."-".$data['name'];
You can also use json_encode() and json_decode() in lou of serialize() and unserialize(). The benefit of using JSON is you can decode it with other languages like JavaScript whereas seialize() is a PHP-specific function.
There's 2 methods in CodeIgniter to insert data in the database.
1st Method: normal SQL query
public function addProduct($code, $name, $photo, $data = array()){
$sql = "";
if($photo == null){
// Product data
$d_code = isset($data['code']) ? $this->db->escape($data['code']) : '';
$d_name = isset($data['name']) ? $this->db->escape($data['name']) : '';
$d_category_id = isset($data['category_id']) ? $this->db->escape($data['category_id']) : '';
$d_subcategory_id = isset($data['subcategory_id']) ? $this->db->escape($data['subcategory_id']) : '';
$sql = "INSERT INTO mytable (code, name, category_id, subcategory_id) ";
$sql .= "VALUES ('" . $d_code . "', '" . $d_name . "', '" . $d_category_id . "', '" . $d_subcategory_id . "')";
} else {
// Product data
$d_code = isset($data['code']) ? $this->db->escape($data['code']) : '';
$d_name = isset($data['name']) ? $this->db->escape($data['name']) : '';
$d_category_id = isset($data['category_id']) ? $this->db->escape($data['category_id']) : '';
$d_subcategory_id = isset($data['subcategory_id']) ? $this->db->escape($data['subcategory_id']) : '';
$d_image = isset($photo) ? $this->db->escape($photo) : '';
$sql = "INSERT INTO mytable (code, name, category_id, subcategory_id, image) ";
$sql .= "VALUES ('" . $d_code . "', '" . $d_name . "', '" . $d_category_id . "', '" . $d_subcategory_id . "', '" . $d_image . "')";
}
$this->db->query($sql);
if($this->db->affected_rows() > 0){
return true;
} else {
return false;
}
}
2nd Method: ActiveRecord
public function addProduct($code, $name, $photo, $data = array()){
if($photo == null){
// Product data
$d_code = isset($data['code']) ? $this->db->escape($data['code']) : '';
$d_name = isset($data['name']) ? $this->db->escape($data['name']) : '';
$d_category_id = isset($data['category_id']) ? $this->db->escape($data['category_id']) : '';
$d_subcategory_id = isset($data['subcategory_id']) ? $this->db->escape($data['subcategory_id']) : '';
$dataArr = array(
'code' => $d_code,
'name' => $d_name,
'category_id' => $d_category_id,
'subcategory_id' => $d_subcategory_id
);
} else {
// Product data
$d_code = isset($data['code']) ? $this->db->escape($data['code']) : '';
$d_name = isset($data['name']) ? $this->db->escape($data['name']) : '';
$d_category_id = isset($data['category_id']) ? $this->db->escape($data['category_id']) : '';
$d_subcategory_id = isset($data['subcategory_id']) ? $this->db->escape($data['subcategory_id']) : '';
$d_image = isset($photo) ? $this->db->escape($photo) : '';
$dataArr = array(
'code' => $d_code,
'name' => $d_name,
'category_id' => $d_category_id,
'subcategory_id' => $d_subcategory_id,
'image' => $d_image
);
}
$this->db->insert('mytable', $dataArr);
if($this->db->affected_rows() > 0){
return true;
} else {
return false;
}
}
Notes
Keep in mind that in both ways you should have the exact structure in the MySQL database. Otherwise you'll have errors such as "column not found" etc.
On another hand, you can't store an array in MySQL, but you can store a comma-separated value (CSV) string, although it's not recommended at all:
$dataArr = array(
$d_code,
$d_name,
$d_category_id,
$d_subcategory_id
);
$csv = implode(",", $dataArr);
This solution will cause problems if any of the data provided contains a comma.
Why you shouldn't store a CSV in a MySQL row:
every piece of information should be treated and saved on its own.
searching within the data will be impossible using MySQL.
forget about "indexing". It's useless in this case. Also, forget about query optimization.
you're looking for a specific piece of information, then you should probably query all the table and loop over this information to get the data you're looking for.
no developers will understand your move.
it'll definitely cause you problems in CodeIgniter, especially in the ActiveRecord methods.
it's really easy to insert/select/update/delete info from the database in CodeIgniter: link
if it's the first time you're working on CodeIgniter, then take a few more minutes reading the docs and learn it well. Doing awful hacks won't help anyone and especially you, because you'll end up with bugs and a messy code.
I have a table with 7 fields, when I delete a row from the table by id i want two fields of that row to be inserted into another table with just two columns.
This is my controller function
public function refund() {
$id = $this->uri->segment(4);
$accounts = $this->accounts_model->get_accounts_data_by_id($id);
foreach ($accounts as $row) {
$data = array(
'barcode' => $row->barcode,
'refunded_amount' => $row->refunded_amount,
);
}
$this->accounts_model->insert_refund($data);
$this->accounts_model->delete_accounts_data($id);
}
these are model functions
public function delete_accounts_data($id) {
$this->db->where('id', $id);
$this->db->delete('accounts');
}
public function insert_refund($data){
$this->db->insert('refund', $data);
}
Suppose this the row i will delete
id|name|barcode|refunded_amount|commission
01|asd |2342342| 53.01 | 5.32
on the other hand i will insert as
id|barcode|refunded_amount
01|2342342| 53.01
You should try and debug your code for general errors, e.g,
1) Try to set the environment to development in index.php.
2) Add some debugging code in your function to check for errors.
function refund(){
$id = $this->uri->segment(4);
$accounts = $this->accounts_model->get_accounts_data_by_id($id);
echo $this->db->last_query(); //will produce the query for fetching the details by id
if( isset( $accounts ) && count( $accounts ) > 0 ){
foreach ($accounts as $row) {
$data = array(
'barcode' => $row->barcode,
'refunded_amount' => $row->refunded_amount,
);
}
print_r( $data );
$this->accounts_model->insert_refund($data);
$this->accounts_model->delete_accounts_data($id);
}else{
echo "NO DATA FOUND";
}
}
I have a custom post type for staff, that uses the post title as the persons name. In order to sort this by last name I'm using an order filter to find the last word in the title and then sort by it:
function posts_orderby_lastname ($orderby_statement)
{
$orderby_statement = "RIGHT(post_title, LOCATE(' ', REVERSE(post_title)) - 1) ASC";
return $orderby_statement;
}
This works great for most of the staff which have normal first and last names, but I can't figure out how would I do this for names like (all should be ordered by "Clause":
Santa Clause
Santa Clause III
Santa Clause Jr.
Santa Clause Kringle
M. Santa Clause Sr.
I assume I can have a stored array and then check for those terms (like "Jr.", "II", etc.) or check for the length of the term found is greater than maybe 3, but I have no idea how to implement that into the code. Any ideas or help would be greatly appreciated - thanks in advance!
I had a similar issue, this is how I solved it. You could expand on the if statement for all the edge cases you describe.
$args = array(
'post_type' => 'page',
'orderby' => 'menu_order',
'posts_per_page' => -1,
'post_parent' => $post->ID,
'order' => 'ASC'
);
$posts = get_posts( $args );
// Order by second word in title, deal with edge cases
$lastname = array();
foreach( $posts as $key => $post ) {
$word = explode( ' ', $post->post_title );
$name = null;
if( strlen($word[1]) == 1 ) {
// Second word only 1 letter, so use third word if set
$name = $word[2];
} elseif( $word[3] == 'Sr.' ) {
// Third word is 'Sr.', so use 2nd word
$name = $word[1];
} else {
$name = $word[1];
}
$lastname[$key] = $name;
}
array_multisort( $lastname, SORT_ASC, $posts );
// Loop through posts
foreach( $posts as $post ) {
echo $post->post_title;
}
I slightly modified to fit my needs, because my names were like
Dawn A. Adelson
Timothy smith
John A. Smith, Jr.
$args = array(
'post_type' => 'YOUR_POST_TYPE',
'posts_per_page' => -1,
'order' => 'ASC'
);
$posts = get_posts( $args );
// Order by second word in title, deal with edge cases
$lastname = array();
foreach( $posts as $key => $post ) {
$word = explode( ' ', $post->post_title );
$name = null;
if( strlen($word[1]) == 2 ) {
// Second word 1 letter and dot, so use third word if set
$name = $word[2];
} elseif( $word[3] == 'Jr.' ) {
// Third word is 'Jr.', so use 2nd word
$name = $word[2];
} else {
$name = $word[1];
}
$lastname[$key] = $name;
}
array_multisort( $lastname, SORT_ASC, $posts );
// Loop through posts
foreach( $posts as $post ) {
?>
<div>
<?php echo $post->post_title; ?>
</div>
<?php
}
?>
</div>
Here's a way better approach, at least the other ones didn't work at all for me.
This will drop anything before the first space and apply a standard sort on the rest of the string. Make sure to modify is_main_query() and is_category() to your actual needs.
function posts_orderby_lastname( $orderby_statement )
{
if( is_main_query() && is_category() ) {
return "SUBSTRING_INDEX(post_title, ' ', -1)";
} else {
return $orderby_statement;
}
}
Try these plugins. It will help you.
http://wordpress.org/plugins/post-types-order/
http://wordpress.org/plugins/intuitive-custom-post-order/
http://wordpress.org/plugins/advanced-custom-sort/
I am writing code in php to basically 'map' data from a mySQL database to another database. I am using the code as follows:
$results = $this->query("select PT_FS_DATA_ID from PATIENT_FLOWSHEET_DATA where
DT_LAST_UPDATED_TIME = (select top 1 DT_LAST_UPDATED_TIME from PATIENT_FLOWSHEET_DATA
order by DT_LAST_UPDATED TIME desc) group by PT_FS_DATA_ID;");
however, I am getting an error:
syntax error, unexpected T_VARIABLE, expecting T_FUNCTION
Everywhere I look this seems to be the correct syntax. Is there something I'm missing here?
I tried putting the controller in there as well $this->controllerName->query, but that didn't work either.
Full Code:
class CaExtraFlowsheetFields extends CaBase {
public $name = 'CaExtraFlowsheetFields';
/*
NOTE: This is to take all the fields in flowsheet and
maps their id's.
*/
//public $useTable = 'ANSWER_ENTRY';
public $useTable = 'PATIENT_FLOWSHEET_DATA';
public $primaryKey = 'PT_FS_DATA_ID';
protected function getPrimaryKeyValue(
$hospital_id,
$patient_id,
$admission_id = null
) {
return $patient_id;
}
//*CHANGE BEGIN*
$results = $this->query("select PT_FS_DATA_ID from PATIENT_FLOWSHEET_DATA where
DT_LAST_UPDATED_TIME = (select top 1 DT_LAST_UPDATED_TIME from PATIENT_FLOWSHEET_DATA
order by DT_LAST_UPDATED TIME desc) group by PT_FS_DATA_ID;");
protected $filedMethodMappings = array(
'Method_GO' => array(
CaBase::KEY_MAPPING_LOGIC_COMPLEXITY => CaBase::LEVEL2_COMPLEXITY,
CaBase::KEY_FIELD_LOGIC_NAME => 'wsMethod_GO',
);
//########################################################################//
//Note[]>Block[] //
//>Method that calls LookUpField for every field in flowsheet // //
//########################################################################//
public function wsMethod_GO ($params) {
foreach($results as $value){
$questionName = ''.$value;
$msg_prefix = $this->name . "::" . __FUNCTION__ . ": ". "arrivez-vouz" ;
$ret = $this->wsLookUpField($params,$questionName,$msg_prefix);
return $ret;
}
unset($value);
}
//########################################################################//
public function wsLookUpField($params,$questionName,$msg_prefix){
$arrayValues=array();
try{
$hospital_id = $params[Constants::KEY_HOSPITAL_ID];
$patient_id = $params[Constants::KEY_PATIENT_ID];
$admission_id = $params[Constants::KEY_ADMISSION_ID];
$msg_prefix = $this->name . "::" . __FUNCTION__ . ": ". "attendez-vouz: l'hopital= ".$hospital_id.
" patient= ".$patient_id." admission= ".$admission_id;
//shows info about given question name
$msg_prefix = "*!*!*!*Show me ---> ".$questionName." : ".$answer_entry_id.
" = aic: " .$answer_id_check;
$ret = array();
//now with needed fields, grab the A_NAME:
$params = array(
'conditions' => array(
$this->name . '.PID' => $patient_id,
$this->name . '.PT_FS_DATA_ID' => $questionName,
),
'order' => array(
$this->name . '.' . $this->primaryKey . ' DESC'
),
'fields' => array(
$this->name . '.FS_VALUE_TEXT',
)
);
$rs = $this->find('first', $params);
/* check to make sure $rs has received an answer from the query
and check to make sure this answer is a part of the most recent
database entries for this note */
if (false != $rs) {
try {
$msg = $msg_prefix . "Data obtained successfully."."<br>".$result;
$result = $rs;
$ret = WsResponse::getResponse_Success($msg, $result);
} catch (Exception $e) {
$msg = $msg_prefix . "Exception occurred.";
$ret = WsResponse::getResponse_Error($msg);
}
/*answer was not part of most recent database entries, meaning no
answer was given for this particular question the last time this
particular note was filled out. Message is given accordingly.*/
} else {
$msg = $msg_prefix . "/No answer given.";
$ret = WsResponse::getResponse_Error($msg);
}
} catch (Exception $e) {
$msg = $msg_prefix . "Exception occurred.";
$ret = WsResponse::getResponse_Error($msg);
}
return $ret;
}
Here is what you are doing:
class ABC {
$result = 'whatever';
}
You can't declare a variable there!
Code needs to be inside a method/function...
class ABC
{
public function wsMethod_GO ($params)
{
$result = 'whatever';
}
}