SQL Compare Characters in two strings count total identical - sql

So the over all on this is I have two different systems and in both systems I have customers, unfortunately both systems allow you to type in the business name freehand so you end up with the example below.
Column A has a value of "St John Baptist Church"
Column B has a value of "John Baptist St Church"
What I need to come up with is a query that can compare the two columns to find the most closely matched values.
From there I plan to write a web app where I can have someone go through and validate all of the entries. I would enter in some example of what I have done, but unfortunately I honestly dont even know if what I am asking for is even possible. I would think it is though in this day and age I am sure I am not the first one to try to attempt this.

You could try and create a script something like this php script to help you:
$words = array();
$duplicates = array();
function _compare($value, $key, $array) {
global $duplicates;
$diff = array_diff($array, $value);
if (!empty($diff)) {
$duplicates[$key] = array_keys($diff);
}
return $diff;
}
$mysqli = new mysqli('localhost', 'username', 'password', 'database');
$query = "SELECT id, business_name FROM table";
if ($result = $mysqli->query($query)) {
while ($row = $result->fetch_object()) {
$pattern = '#[^\w\s]+#i';
$row->business_name = preg_replace($pattern, '', $row->business_name);
$_words = explode(' ', $row->business_name);
$diff = array_walk($words, '_compare', $_words);
$words[$row->id][] = $_words;
$result->close();
}
}
$mysqli->close();
This is not tested but you need something like this, because I don't think this is possible with SQL alone.
---------- EDIT ----------
Or you could do a research on what the guys in the comment recommend Levenshtein distance in T-SQL
Hope it helps, good luck!

Related

Hibernate Search DSL and Lucene query on Multiple Fields

I'm not really sure how involved this might be, but could someone help me with below problem.
I'm trying to implement search functionality in my project based on employee firt and last name. I have used Spring Data REST and Hibernate Search for this purpose.
#Transactional
public search(String searchText) {
FullTextEntityManager fullTextEntityManager = org.hibernate.search.jpa.Search
.getFullTextEntityManager(entityManager);
QueryBuilder qb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Employee.class).get();
org.apache.lucene.search.Query luceneQuery = qb.keyword().wildcard()
.onFields("firstName", "middleName", "lastName").matching(searchText + "*").createQuery();
javax.persistence.Query jpaQuery = fullTextEntityManager.createFullTextQuery(luceneQuery, Employee.class);
List result = jpaQuery.getResultList();
List<EmployeeSearchDTO> listOfDTO = new ArrayList<>();
EmployeeSearchDTO employeeDTO;
Iterator<Employee> itr = result.iterator();
while (itr.hasNext()) {
Employee employee = itr.next();
employeeDTO = new EmployeeSearchDTO(employee);
listOfDTO.add(employeeDTO);
}
}
When I search "john doe" i expect the results should match the below two
FirstName : John LastName : Doe
FirstName : johnathan LastName : Doe
But that is not the case and I'm able to search only based on FirstName["john"] or LastName["doe"] but not with both.
How do I solve this, any pointers would be greatly appreciated. Thanksin advance.
You really want to create two queries, one against the first name and one against the last name and then combine them via the SHOULD operator. Something like
Query combinedQuery = querybuilder
.bool()
.should( firstNameQuery )
.should( lastNameQuery )
.createQuery();
This means you are looking for results where either of the queries match.

ZF2: Is there a more efficient way to do this Zend\Db Update query?

Here's some ZF1 code for an update query:
$this->getAdapter()->update(
'users', $data, $this->getAdapter()->quoteInto('node_id = ?', $user->nodeId)
);
Here's the same query with ZF2:
$param = $this->getAdapter()->platform->quoteValue($user->nodeId);
$sqlOj = new Sql($this->getAdapter());
$update = $sqlOj->update('users')->set($data)->where('node_id = ' . $param);
$updateString = $sqlOj->getSqlStringForSqlObject($update);
$this->getAdapter()->query($updateString, Adapter::QUERY_MODE_EXECUTE);
As you can see, one line of ZF1 code has become 5 lines of ZF2 code, (actually without the fluent interface it would be 7 lines...)
Am I missing something? Or is ZF2's DB component just more verbose that ZF1?
BTW, I have found the same scenario with select and insert queries too...
I managed to limit it to 3 lines.
use \Zend\Db\Sql\Sql;
$sql = new Sql ($adapter);
$update = $sql->update ('users')->set ($data)->where (['id = ?' => 1]);
$adapter->query ($sql->getSqlStringForSqlObject ($update), $db::QUERY_MODE_EXECUTE);
The problem is they didn't expect you to run your updates like that. Instead, you are expected to use a table gateway.
This way it becomes one line again:
$this->tableGateway->update($data, array('id' => $id));

$data = $query->row(); returns only one row

Im trying to list the results of my sql query (picking up all the movies from a category), but I cannot figure out how to get all the rows instead of only one.
Here's the code :
$this->load->database();
$sql = 'SELECT * FROM movies WHERE category = "'.$movies_category.'";';
$query = $this->db->query($sql);
$data = $query->row();
$this->response($data, 200);
I've tried :
while($row = mysql_fetch_assoc($query)){
$data = $query->row();
}
$this->response($data, 200);
And it doesn't work. Any suggestion ? Thank you !
$this->load->database();
$sql = 'SELECT * FROM movies WHERE category = "'.$movies_category.'";';
$query = $this->db->query($sql);
$data = $query->result();
To traverse the $data array:
foreach($data AS $row)
{
//to retrieve the data from each row.
$col1 = $row->col1;
$col2 = $row->col2;
}
Use result() instead of row(). result() will return an array of objects that are your results. Alternatively, you can useresult_array() which will resturn an array of arrays keyed according to your columns. Please refer to here for a better outline of the result() and row() methods.
Do you have a database configuration file? the load->database() requires it. Where is $movies_category coming from? This will let you iterate over your results.
$this->load->database();
$sql = 'SELECT * FROM movies WHERE category = "'.$movies_category.'";';
$query = $this->db->query($sql);
foreach ($query->result() as $row)
{
echo $row->column;
}
Where column corresponds with one of the values in the movies table.
I'm surprised nobody has mentioned the potential hazards of using variables (possibly user input) in your SQL. You should seriously consider using query bindings or the active record features of CodeIgniter to build safer queries.
Consider the following solution to your problem:
$this->load->database();
$sql = 'SELECT * FROM movies WHERE category = ?';
$query = $this->db->query($sql, array($movies_category));
// $data = $query->result(); // returns result as an array of objects
$data = $query->result_array(); // returns result as array
$this->response($data, 200);
I'm assuming this is for some sort of API? If so, consider using the result_array() method as it will probably be better suited for your needed output, and also really easy to convert into JSON:
$json_data = json_encode($data);
Hope that helps,
Cheers.
For your question row() return only one value its good for checking in ID and if you want get all the rows use result_array() or simple result()
You can try this code....
Model:
function get_movies($movies_category){
$this->db->where("category",$movies_category);
$query = $this->db->get("movies");
return $query->result_array();
}
Controller:
$this->data['movies'] = $this->'name of model'->get_movies('here is the movie categories');
View:
foreach($movies as $m){
print_r($m);
}
exit();
Note you can directly add the code in function in model to controller add this in your controller if you want directly...
$this->data['movies] = $this->db->get('movies')->result_array();

codeigniter change complex query into active record

I have a codeigniter app.
My active record syntax works perfectly and is:
function get_as_09($q){
$this->db->select('m3');
$this->db->where('ProductCode', $q);
$query = $this->db->get('ProductList');
if($query->num_rows > 0){
foreach ($query->result_array() as $row){
$row_set[] = htmlentities(stripslashes($row['m3'])); //build an array
}
return $row_set;
}
}
This is effectively
select 'm3' from 'ProductList' where ProductCode='$1'
What I need to do is convert the below query into an active record type query and return it to the controller as per above active record syntax:
select length from
(SELECT
[Length]
,CONCAT(([width]*1000),([thickness]*1000),REPLACE([ProductCode],concat(([width]*1000),([thickness]*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options
FROM [dbo].[dbo].[ProductList]) as p
where options='25100cr' order by length
I picture something like below but this does not work.
$this->db->select(length);
$this->db->from(SELECT [Length],CONCAT(([width]*1000),([thickness]*1000),REPLACE[ProductCode],concat(([width]*1000),([thickness]*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options
FROM [dbo].[dbo].[ProductList]);
$this->db->where(options, $q);
$this->db->order(length, desc);
Help appreciated as always. Thanks again.
You can use sub query way of codeigniter to do this for this purpose you will have to hack codeigniter. like this
Go to system/database/DB_active_rec.php Remove public or protected keyword from these functions
public function _compile_select($select_override = FALSE)
public function _reset_select()
Now subquery writing in available And now here is your query with active record
$select = array(
'Length'
'CONCAT(([width]*1000)',
'thickness * 1000',
'REPLACE(ProductCode, concat((width*1000),(thickness*1000),REPLACE((convert(varchar,convert(decimal(8,1),length))),'.','')),'')) as options'
);
$this->db->select($select);
$this->db->from('ProductList');
$Subquery = $this->db->_compile_select();
$this->db->_reset_select();
$this->db->select('length');
$this->db->from("($Subquery)");
$this->db->where('options','25100cr');
$this->db->order_by('length');
And the thing is done. Cheers!!!
Note : While using sub queries you must use
$this->db->from('myTable')
instead of
$this->db->get('myTable')
which runs the query.
Source

Issue in making appear all database table field names

I have this code which i use in order to make appear all the names of a table of a database.
It used to work... but suddenly it won't make appear anything..
Could you please take a look?
I'm working with SQL.
$section = "SELECT * FROM forma";
$res = odbc_exec($connection, $section) or die(odbc_error());
$firstrow = false;
while ($row = odbc_fetch_array($res)){
if (!$firstrow) {
foreach ($row as $column => $value) {
echo "<label> " . $column . "</label>";
echo "<input type='checkbox' name='data[]' value='" . $column . "' /><br/><br/>";
}
$firstrow = true;
}
}
Thanks
This is a fairly nasty way of retrieving the column names for a table. What it is doing is reading all the data in the table, ignoring the result set and only using it for the column names. What is happening however is that the table is empty and so nothing is being returned at all.
You need to amend the query to look at the meta data rather than the table itself. You will need to rework it. This SQL will retrieve the column names for that table for you...
Select Columns.Name
From Sys.Columns
Where Object_Name(Columns.Object_id) = 'forma'
Order By Columns.Column_Id;
After that you will need to rejig your code to take advantage of it.