Select query with prefix on all column elements - mysql

Is it possible to create a database query in which I add a prefix to every single
column of a table. Because the tables unfortunately have "too many" columns I
would like to avoid assigning an alias to every single column.
Goal:
select table1.*, table2 Will output: table1_id, table_1_name, table2_id, table_2_name, ...
Is this possible?
That is my approach:
$data = DB::connection('mysql_wp')->table('wp_posts as p')
->selectRaw('p.*, m.*')
->join('wpao_metas as m', 'm.post_id', '=', 'p.ID')
->get();
dd($data);
But i didnt work. I got columnnames without prefixe.

You could use a helper function to alias the corresponding columns.
public function getColumnAliases(string $table, string $prefix = null): array
{
$prefix = $prefix ?? $table . "_";
return array_map(function ($column) use ($table, $prefix) {
return $table . "." . $column . " AS " . $prefix . $column;
}, \Illuminate\Support\Facades\DB::getSchemaBuilder()->getColumnListing($table));
}
Then in your select(...) query:
Instead of ❌:
->selectRaw('p.*, m.*')
Use this ✅:
->select(
array_merge(
$this->getColumnAliases("wp_posts"),
$this->getColumnAliases("wpao_metas")
)
)
Notes:
You may pass a custom prefix as the second argument of the getColumnAliases(...) method.

Related

Laravel Eloquent: Query returns no records but SQL does

I have this query:
$query = City::query();
$query->select('id', 'name as default_name', 'translations->' . $request["lang"] . ' as name', 'country_id');
$query->where(function ($query) use ($request) {
$query->whereRaw('LOWER(translations->"$.' . $request["lang"] . '") like ?', "'%" . strtolower($request['search']) . "%'");
$query->orWhere('name', 'like', "'%" . strtolower($request->search) . "%'");
});
if ($request->country !== null) {
$query->whereRaw('country_id = '. $country);
}
$results = $query->get();
That translates to this SQL:
select `id`, `name` as `default_name`, json_unquote(json_extract(`translations`, '$."en"')) as `name`, `country_id`
from `cities`
where (LOWER(translations->"$.en") like '%barcelona%' or `name` like '%barcelona%')
and country_id = 207
Eloquent is not returning any records while SQL does:
Any clue on whats wrong here?
Thanks!
Is Ok the part?
if ($request->country !== null) {
$query->whereRaw('country_id = '. $country);
}
Its seems like
if ($request->country !== null) {
$query->where('country_id', $request->country);
}
And in the select part the JSON column not has $ operator.
This line in the code seemed to be the problem:
$query->orWhere('name', 'like', "'%" . strtolower($request->search) . "%'");
I found a solution using orWhereRaw():
$query->orWhereRaw('LOWER(`name`) LIKE ? ','%'. trim(strtolower($request['search'])) .'%')
This line converts column "name" data to lowercase and trims and lowers the search parameter.
I hope it help others in the future.

How to select all columns except one in Yii2?

What I need to do is to select all the database columns except one.
I have something like:
$foo = self::find()
->select([
self::tableName() . '.*'
]);
It's selecting all the columns, but how to do that one column wouldn't be selected? Obviously I can tell to select a specific columns like this:
$foo = self::find()
->select([
self::tableName() . '.column1',
self::tableName() . '.column2',
self::tableName() . '.column3'
...
]);
But the database table is really big, so I'm looking for a proper way to do it..
Any ideas? Thank you for your time
You need not mention self::tableName() . '.column1', all the time.
You can just add all the fileds in your db table in the model and use them as follows.
Your model should contain method for returning fields,something like this
public function fields() {
return[
'id',
'column1',
'column2',
'column3',
'created_at',
'updated_at',
etc...
];
}
Then You can just call the fields into the query like
$foo = self::find()
->select([
'column1',
'column2',
'column3',
...
]);
Now, coming to your question, we can just call all the fields as self::fields(), which returns a array of fields in your table.
Then, you can remove that specific field from the array we got,by doing something like this
if (($key = array_search('strawberry', $array)) !== false) {
unset($array[$key]);
}
Then, we have the sorted array without the field that is not required.
Now, you pass the sorted array to the Query as
$foo = self::find()
->select([
$array
]);
As variant you can try to form column list dynamically and use it
// variant 1
$columns = Yii::$app->db->createCommand("SELECT column_name FROM information_schema.columns WHERE table_name = 'user' AND table_schema = database()")->queryAll();
$out_columns = [];
foreach ($columns as $item) {
if (! in_array($item['column_name'], ['auth_key', 'password_hash', 'password_reset_token'])) {
$out_columns[] = $item['column_name'];
}
}
print_r($out_columns);
print_r(User::find()->select($out_columns)->one());
// variant 2
$columns = Yii::$app->db->createCommand("SELECT column_name FROM information_schema.columns WHERE table_name = 'user' AND column_name NOT IN('auth_key', 'password_hash', 'password_reset_token') AND table_schema = database()")->queryAll();
$out_columns = [];
foreach ($columns as $item) {
$out_columns[] = $item['column_name'];
}
print_r($out_columns);
print_r(User::find()->select($out_columns)->one());

Joomla SQL query alternative

I have the following getListQuery() in my model. I want to add another join (see further) and was wondering if the level part could be done another way (without GROUP_CONCAT):
protected function getListQuery()
{
$db = $this->getDbo();
$query = $db->getQuery(true);
$query->select(
$this->getState(
'list.select',
'a.id AS id,' .
'a.dbid AS dbid,' .
'a.alias AS alias,' .
'GROUP_CONCAT(DISTINCT l.level ORDER BY l.level ASC) as `levels`'
)
);
$query->from('#__maintable AS a');
$query->join('LEFT', '#__leveltable AS l ON l.dbid = a.dbid');
$query->group($db->quoteName('a.id'));
$query->order($db->escape($this->state->get('list.ordering', 'a.id') . ' ' . $db->escape($this->state->get('list.direction', 'ASC'))));
return $query;
}
In the leveltable there can be more then one row with a corresponding 'dbid'.
I would also like to add a second table which has a relation to 'dbid' which also can have multiple rows with the same 'dbid' and it has more fields I would require then just the 'level' field from leveltable.

SQL QUERY SELECT INSIDE A FUNCTION

I am trying to work with a voting database system. I have a form to display all the candidates per candidate type. I'm still trying to to explore that. But this time, I want to try one candidate type, lets say for Chairperson, I want to display all candidate names for that type in the ballot form. However, there's an error with the line where i declare $query and made query statements, can somebody know what it is. I am very certain that my syntax is correct.
function returnAllFromTable($table) {
include 'connect.php';
$data = array ();
$query = 'SELECT * FROM ' . $table. 'WHERE candidateId=1'; //ERROR
$mysql_query = mysql_query ( $query, $conn );
if (! $mysql_query) {
die ( 'Go Back<br>Unable to retrieve data from table ' . $table );
} else {
while ( $row = mysql_fetch_array ( $mysql_query ) ) {
$data [] = $row;
}
}
return $data;
}
As #Darwin von Corax says, I sure that you have a problem between $table and WHERE
Your query:
$query = 'SELECT * FROM ' . $table. 'WHERE candidateId=1';
If $table = 'Chairperson';
You have:
'SELECT * FROM ChairpersonWHERE candidateId=1';
The your query should be:
$query = 'SELECT * FROM ' . $table. ' WHERE candidateId=1';

Search in model and in its relations and paginate results

So I'm building an ECommerce site using Laravel/MySQL, the product related tables I have are as follows: 'products', 'attributes', 'taxonomies' and 'tags'. When a user types a keyword to search for product, I want to search all 4 tables with one query to get the desired products, then I want to use Laravel paginate function to paginate the result, now how do I make it done in one query? Maybe some joins involved?
Here it is, the relationship of my database tables, as for my models, it is defined like this:
class Product extends Eloquent {
...
public function taxonomies() {
return $this->belongsToMany('Taxonomy', 'product_taxonomy', 'product_id', 'taxonomy_id');
}
...
// Same goes for attributes and labels
public function reviews() {
return $this->hasMany('Review', 'product_id');
}
}
Maybe you want something like this:
$products = Product::where('name', 'LIKE ', '%' . $keyword . '%');
$products = $products->orWhereHas('attributes',
function ($query) use ($keyword) {
$query->where('name', 'LIKE ', '%' . $keyword . '%');
}
);
$products = $products->orWhereHas('taxonomies',
function ($query) use ($keyword) {
$query->where('name', 'LIKE ', '%' . $keyword . '%');
}
);
$products = $products->orWhereHas('tags',
function ($query) use ($keyword) {
$query->where('name', 'LIKE ', '%' . $keyword . '%');
}
);
$products = $products->paginate(10);
Now you look in product name and in names of your relations (tags, taxonomies and attributes) and paginate 10 products.
You can try like this
$data = DB::table('products')
->join('attributes', 'products.attributes_id', '=', 'attributes.id')
->join('taxonomies', 'products.taxonomies_id', '=', 'taxonomies.id')
->join('tags', 'host_vulnerabilities.tags_id', '=', 'tags.id')
->where('products.id', '=', $id)
->select('products.id', 'attributes.name') //all required fields
->paginate(15);
I have just added sample example. Please update code as per your requirement
Use UNION for this,
SELECT product_id, product name FROM Products WHERE keyword = 'my_keyword' UNION
SELECT product_id, product name FROM Attributes WHERE keyword = 'my_keyword' UNION
..... Same for other tables
Moreover it will filter out repeated results as UNION works as UNION DISTINCT. But if you provide us with a schema or some db structure, can provide a better solution.
For Laravel, this may work you can create a view and query the view instead of the actual tables, or create your Paginator manually:
$page = Input::get('page', 1);
$paginate = 10;
$w1 = 'my_keyword';
$first = DB::table('products')->where('attribute', 'like', '"%'.$w1.'%"');
$second = DB::table('attributes')->where('attribute', 'like', '"%'.$w1.'%"');
$third = DB::table('taxonomies')->where('attribute', 'like', '"%'.$w1.'%"');
$fourth = DB::table('tags')->where('attribute', 'like', '"%'.$w1.'%"');
$union1 = $first->union($second);
$union2 = $third->union($union1);
$union3 = $fourth->union($union2);
$union3->get();
$slice = array_slice($union3, $paginate * ($page - 1), $paginate);
$result = Paginator::make($slice, count($union3), $paginate);
return View::make('yourView',compact('result'));